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
答案 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)
float
和double
是具有不同精度的不同类型。
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);