5
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

4 回答 4

5

3.1定义一个doublewhile3.1f定义一个float. 您看到的是float表示该值的问题(浮点使用“仅”32 位和双 64 位)。

如果你想定义一个3.1完全使用BigDecimal使用String构造函数:

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

输出:

3.1
于 2012-07-19T09:32:49.063 回答
0

float并且double是具有不同精度的不同类型。

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

float恕我直言,除非您有充分的理由这样做,否则不要使用。

于 2012-07-19T09:34:19.810 回答
0

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

以 0.1 为例,没有办法以 2 为底准确表示这一点,就像无法以 10 为底准确表示 1/3 一样。

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

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

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

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

例如,值 3.1 将在 BigDecimal 中表示为 31,precision=1 因此,BigDecimal 不会遭受与浮点数和双精度数相同的舍入问题。

但是,当您使用浮点/双精度值来初始化 BigDecimal 时,相同的舍入错误会导致它进入 BigDecimal 实例。这就是为什么建议使用 String 来构造值的原因。

于 2012-07-19T13:17:28.203 回答
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);
于 2014-02-06T17:46:34.837 回答