如何在JSP / Java中从double中获得全部和分数部分?


104

如何在JSP / Java中从double中获得全部和分数部分?如果值为3.25,那么我想得到fractional =.25whole = 3

我们如何用Java做到这一点?


4
您似乎对尾数和指数不了解。它们不只是“整个部分”和“分数部分”。参见en.wikipedia.org/wiki/Floating_point
Jon Skeet

实际上,我读过大约5篇文章,然后说“嘿..那不叫指数”。我的大脑抛出了单词,开始解决问题..阅读编程内容的不良习惯给了我:)
Gishu

1
另外,出于其他原因,也请改后题OP..。
Gishu

1
听起来可疑像是一个家庭作业问题。
Brian Knoblauch

哦,我明白了。我已经想知道他如何得到如此奇怪的结果
约翰内斯·绍布

Answers:


102

http://www.java2s.com/Code/Java/Data-Type/Obtainingtheintegerandfractionalparts.htm

double num;
long iPart;
double fPart;

// Get user input
num = 2.3d;
iPart = (long) num;
fPart = num - iPart;
System.out.println("Integer part = " + iPart);
System.out.println("Fractional part = " + fPart);

输出:

Integer part = 2
Fractional part = 0.2999999999999998

61
实际上,此页面是Google搜索“从double java中获取小数部分和整个部分”
克里斯,克里斯

12
实际上,这个答案是不正确的,因为大于long的值可以表示它会在小数部分给出巨大的数字。丹·文顿(Dan Vinton)的回答很简单,并且总是返回正确的结果。
Arberg 2012年

2
所以实际上,这是不正确的,正如您在输出中看到的那样。输入是3的分数,输出是29999999 ...尽管使用BigDecimal而不是Double可以解决问题
Alex

2
@Alex不,输入的数字非常接近2.3,但肯定不是2.3。除非您想要的有效位数超过10个,否则输出没有任何问题。您需要做的是在每个输出中进行四舍五入(例如format %.9f),通常比减轻痛苦BigDecimal。唯一的问题是溢出。
maaartinus

1
将double转换为int几乎总是一个坏主意。因为例如对于(long)1.0e100您将获得0。很多时候,您需要double值只是简单地“泛滥”了floor()。如果要同时使用积分和分数部分modf()。确实,这是一个错误的答案。
mojuba '16

155
double value = 3.25;
double fractionalPart = value % 1;
double integralPart = value - fractionalPart;

12
为什么这样投票?效果很好,并且通过我的编辑也可以使用负值。
HRJ

整数部分可以是=> long longPart =(long)3.25
jdurango 2014年

2
不会起作用。价值观。即-3.25%1 = 0.75而不是0.25。因此,integratePart将为-3.25-0.75 = -4。
WindRider 2014年

2
@WindRider,我检查了是否为负数及其工作..但是,对于数量较少的小数位,将会有轻微的错误。例如 对于-03.0025,它返回-0.0024999999999999467和-3.0
justshams

5
这里的困惑是因为某些语言(例如Python)用于%表示模(-3.25 % 1 == 0.75),而其他语言(例如Java,Fortran,C和C ++)用于%表示余数(-3.25 % 1 == -0.25)。为了方便起见,WindRider可能已将其键入Python REPL中,但该答案具有误导性,因为此问题与JVM有关。
Jim Pivarski 2015年

24

由于这个1岁的问题是由纠正问题主题的人提出的,因此该问题被标记为 jsp,并且这里没有人能够给出以JSP为目标的答案,所以这是我以JSP为目标的贡献。

使用JSTL(只需将jstl-1.2.jar放入/WEB-INF/libfmt taglib中。有一个<fmt:formatNumber>标签,它可以在maxFractionDigitsmaxIntegerDigits属性的帮助下以非常容易的方式完全满足您的需求。

这是一个SSCCE,只需复制“ 粘贴 ”即可运行它。

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<%
    // Just for quick prototyping. Don't do this in real! Use servlet/javabean.
    double d = 3.25;
    request.setAttribute("d", d);
%>

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 343584</title>
    </head>
    <body>
        <p>Whole: <fmt:formatNumber value="${d}" maxFractionDigits="0" />
        <p>Fraction: <fmt:formatNumber value="${d}" maxIntegerDigits="0" />
    </body>
</html>

输出:

整体:3

分数:.25

而已。无需借助原始Java代码来完善它。


8

最初的问题要求的是指数和尾数,而不是分数和整数部分。

要从双精度中获取指数和尾数,可以将其转换为IEEE 754表示形式,并提取如下位:

long bits = Double.doubleToLongBits(3.25);

boolean isNegative = (bits & 0x8000000000000000L) != 0; 
long exponent      = (bits & 0x7ff0000000000000L) >> 52;
long mantissa      =  bits & 0x000fffffffffffffL;

尾数的第一位不是隐式设置为1,因此尾数应为(bits&0x000fffffffffffffL)| 0x0010000000000000L?
08年

拉斯穆斯不是黑麦输出输出:指数0和尾数2814749767106560,如果您选择urs agnul,则尾数为0
Vinayak Bevinakatti

最终以4票得了高分:)尽管我看到代码试图在联合处去除双精度值,但代码似乎并未输出正确的值。
纪州

@agnul:我认为“尾数”通常仅指位的值。您可能只是通过(有时)在前面加1位来将其转换为有效数。但是根据Wikipedia的说法,现在不建议使用尾数,而使用“分数”。
Rasmus Faber

5

您必须首先找到小数点后的主要数字的主要逻辑。
该代码适用于最多16位数字。如果使用BigDecimal,则最多只能运行18位数字。将输入值(您的数字)放入变量“ num”,此处以示例为例,我对其进行了硬编码。

double num, temp=0;
double frac,j=1;

num=1034.235;
// FOR THE FRACTION PART
do{
j=j*10;
temp= num*j;
}while((temp%10)!=0);       

j=j/10;
temp=(int)num;
frac=(num*j)-(temp*j);

System.out.println("Double number= "+num);      
System.out.println("Whole part= "+(int)num+" fraction part= "+(int)frac);

杜德,这是一个简单问题的极其复杂的答案。您是否看过接受的答案?
灰色

1
现在,做过低票的人(不是我吧)应该解释了为什么会有低票。这不好。但是我们每个人在某些时候或其他方面的得分均为1。
2013年

2
@灰色的问题是将3.25分隔为“ 3”和“ 25”,并且接受的答案永远不会给出“ 25”,它将始终给出“ 2599999999”
OnePunchMan 2013年

@灰色我知道谁对此表示反对,这是一个人名Eji(旧用户)嘲笑我在此博客中发布的每条评论,答案和问题。最后,我向主持人抱怨。
OnePunchMan

2
如果您想把小数部分作为一个整数,则这问题非常有用
Guilherme Campos Hazan

5

IEEE双浮点数的尾数和指数是这样的值:

value = sign * (1 + mantissa) * pow(2, exponent)

如果尾数的形式为0.101010101_base 2(即,其最显着的位移到二进制点之后),并且对指数进行了偏置调整。

从1.6开始,java.lang.Math还提供了一种直接方法来获得无偏指数(称为getExponent(double))。

但是,您要查询的数字是该数字的整数和小数部分,可以使用

integral = Math.floor(x)
fractional = x - Math.floor(x)

尽管您可能希望对负数进行不同的处理(floor(-3.5) == -4.0),具体取决于您为何希望这两部分。

我强烈建议您不要称这些尾数和指数。


4

不知道这样是否更快,但我正在使用

float fp = ip % 1.0f;

3

[编辑:该问题最初询问如何获取尾数和指数。]

其中n是获得实际尾数/指数的数​​字:

exponent = int(log(n))
mantissa = n / 10^exponent

或者,要获得您正在寻找的答案:

exponent = int(n)
mantissa = n - exponent

这些并非完全是Java,但应该易于转换。


3

整数部分来自简单的转换以及分数转换-字符串拆分:

double value = 123.004567890

int integerPart = (int) value; // 123

int fractionPart = 
  Integer.valueOf(String.valueOf(value)
      .split(".")[1]); // 004567890

/**
* To control zeroes omitted from start after parsing.
*/
int decimals =
  String.valueOf(value)
      .split(".")[1].length(); // 9

1

如果您的电话号码是2.39999999999999,该怎么办。我想您想获得确切的十进制值。然后使用BigDecimal:

Integer x,y,intPart;
BigDecimal bd,bdInt,bdDec;
bd = new BigDecimal("2.39999999999999");
intPart = bd.intValue();
bdInt = new BigDecimal(intPart);
bdDec = bd.subtract(bdInt);
System.out.println("Number : " + bd);
System.out.println("Whole number part : " + bdInt);
System.out.println("Decimal number part : " + bdDec);

0

由于fmt:formatNumber标记并不总是能产生正确的结果,因此这是另一种仅JSP的方法:它只是将数字格式化为字符串,并对字符串进行其余的计算,因为这更容易且不涉及进一步的浮点数算术。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<%
  double[] numbers = { 0.0, 3.25, 3.75, 3.5, 2.5, -1.5, -2.5 };
  pageContext.setAttribute("numbers", numbers);
%>

<html>
  <body>
    <ul>
      <c:forEach var="n" items="${numbers}">
        <li>${n} = ${fn:substringBefore(n, ".")} + ${n - fn:substringBefore(n, ".")}</li>
      </c:forEach>
    </ul>
  </body>
</html>

只需尝试我示例中的所有数字即可。fmt:formatNumber四舍五入它的参数,在这种情况下是不需要的。
罗兰·伊利格

0

其中许多答案都有可怕的舍入错误,因为它们将数字从一种类型转换为另一种类型。怎么样:

double x=123.456;
double fractionalPart = x-Math.floor(x);
double wholePart = Math.floor(x);

@justshams那使用Math.abs呢?
斯蒂芬

0

对于-0到-1.0之间的负数,可接受的答案不能很好地工作。还应将小数部分设为负数。

例如:对于数字-0,35

退货

整数部分= 0小数部分= -0.35

如果您正在使用GPS坐标,则最好在整数部分上使用符号表示结果:

整数部分= -0小数部分= 0.35

这些数字例如用于GPS坐标,这对于纬度或经度位置的信号很重要

提出代码:

    double num;
    double iPart;
    double fPart;

    // Get user input
    num = -0.35d;
    iPart = (long) num;
    //Correct numbers between -0.0 and -1.0
    iPart = (num<=-0.0000001 && num>-1.0)? -iPart : iPart ;
    fPart = Math.abs(num - iPart);
    System.out.println(String.format("Integer part = %01.0f",iPart));
    System.out.println(String.format("Fractional part = %01.04f",fPart));

输出:

Integer part = -0
Fractional part = 0,3500


0

我将使用BigDecimal作为解决方案。像这样:

    double value = 3.25;
    BigDecimal wholeValue = BigDecimal.valueOf(value).setScale(0, BigDecimal.ROUND_DOWN);
    double fractionalValue = value - wholeValue.doubleValue();

0
String value = "3.06";

if(!value.isEmpty()){
    if(value.contains(".")){    
        String block = value.substring(0,value.indexOf("."));
        System.out.println(block);
    }else{
        System.out.println(value);
    }
}

该答案被标记为低质量。如果它回答了问题,请考虑添加一些文字以说明其工作原理。
lmo

0
// target float point number
double d = 3.025;

// transfer the number to string
DecimalFormat df = new DecimalFormat();
df.setDecimalSeparatorAlwaysShown(false);
String format = df.format(d);

// split the number into two fragments
int dotIndex = format.indexOf(".");
int iPart = Integer.parseInt(format.substring(0, dotIndex)); // output: 3
double fPart = Double.parseDouble(format.substring(dotIndex)); // output: 0.025

0

好的,这可能已经晚了,但是我认为最好,更准确的方法是使用BigDecimal

double d = 11.38;

BigDecimal bigD = BigDecimal.valueOf(d);
int intPart = bigD.intValue();
double fractionalPart = bigD.subtract(BigDecimal.valueOf(intPart)).doubleValue();

System.out.println(intPart); // 11
System.out.println(fractionalPart ); //0.38

如果您有双精度数,则它具有浮点精度。将其转换为BigDecimal不会神奇地恢复其精度。
塔斯基

@Taschi我认为问题在于将整数和小数部分分开,而不是恢复其精度!
奥马尔·埃拉奇利

奥马尔(Omar),您专门谈到了您的方法“更准确”,我认为这是不正确的。您的回答是完全可以接受的,但该措辞似乎对我产生了误导,这就是为什么我对此发表评论。
塔奇

@Taschi,我说过,因为在很多答案中,当您获得输出时,您会失去价值,例如input (5.03) output int = 5 , fractional = 0.0299999,我们在谈论输入和输出,您投入价值并取回您的价值而不会损失0.001%!而且此准确无误导!
奥马尔·埃拉奇利

是。当您首先将内容存储为双精度时,您会失去精度。转换为BigDecimal时的舍入也会降低精度。这两个精度损失可能会相互抵消,但这并不能“恢复”精度,因为恢复精度在数学上是不可能的。您不能凭空获取信息。
塔奇

-2
public class MyMain2 {
    public static void main(String[] args) {
        double myDub;
        myDub=1234.5678;
        long myLong;
        myLong=(int)myDub;
        myDub=(myDub%1)*10000;
        int myInt=(int)myDub;
        System.out.println(myLong + "\n" + myInt);
    }
}

仅当数字恰好有4个小数位时才有效。并非如此。
罗恩侯爵
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.