Float和BigDecimal精度差异

时间:2012-07-19 09:30:04

标签: java floating-point bigdecimal

public static void main(String[] args) {
    // TODO Auto-generated method stub
    BigDecimal foo,foo1;
    foo=BigDecimal.valueOf(3.1);
    foo1=BigDecimal.valueOf(3.1f);

    System.out.println(foo);
    System.out.println(foo1);

}

结果:
3.1
3.0999999046325684

为什么他们的结果不同?我使用的是JDK1.7.0_03

4 个答案:

答案 0 :(得分:4)

3.1定义double,而3.1f定义float。你看到的是float表示该值的问题(float使用“仅”32位和双64位)。

如果您想完全使用3.1定义BigDecimal,请使用String构造函数:

BigDecimal foo = new BigDecimal("3.1");
System.out.println(foo);

输出:

3.1

答案 1 :(得分:0)

floatdouble是具有不同精度的不同类型。

BigDecimal.valueOf(double)可以纠正double中的表示错误,但不能纠正float中的表示错误

除非您有非常的理由,否则恕我直言不会使用float

答案 2 :(得分:0)

问题是对于float和double,分别使用32位和64位来表示数字的整数和小数部分。当您尝试表示一个小数值时,问题就出现了,该小数值实际上没有二进制位中的精确十进制表示。

以.1为例,没有办法在基数2中准确地表示这一点,只不过可以准确地表示基数为10的1/3。

所以java使用了一些技巧,所以当你说:

float f = 3.1;
System.out.println(f);

打印出正确的数字。但是,当您开始使用这些值进行算术运算时,最终会出现舍入误差。

BigDecimal是准确的,因为它使用不同的表示。它在内部存储一个BigInteger(使用int []来表示大数字)。然后,它使用一个精度值来告诉它在小数点后面有多少个整数位。

例如,值3.1将在BigDecimal中表示为31,precision = 1 出于这个原因,BigDecimal没有遭受相同的舍入问题浮动和双重。

但是,当您使用float / double值初始化BigDecimal时,相同的舍入错误会使它进入BigDecimal实例。这就是为什么建议使用String来构造值。

答案 3 :(得分:0)

由于我想分享的菜鸟错误,我遇到了类似的问题:

BigDecimal bd = new BigDecimal(float); 

这给了我不想要的额外精度,并将其设置为String修复它......

但是,我这样做了:

BigDecimal bd = new BigDecimal(float);
bd.setScale(2, RoundingMode.HALF_UP);

新秀错误。我应该这样做。

bd = bd.setScale(2, RoundingMode.HALF_UP);