java BigDecimal 减法失败

标签 java bigdecimal

我尝试了以下代码。但在使用 BigDecimal 进行减法时会得到不同的结果。

    double d1 = 0.1;
    double d2 = 0.1;
    System.out.println("double result: "+ (d2-d1));

    float f1 = 0.1F;
    float f2 = 0.1F;
    System.out.println("float result: "+ (f2-f1));

    BigDecimal b1 = new BigDecimal(0.01);
    BigDecimal b2 = new BigDecimal(0.01);

    b1 = b1.subtract(b2);
    System.out.println("BigDecimal result: "+ b1);

结果:

double result: 0.0
float result: 0.0
BigDecimal result: 0E-59

我还在研究这个。谁能澄清一下。

最佳答案

[这里有很多答案告诉您二进制 float 不能准确表示 0.01,并暗示您看到的结果在某种程度上是不准确的。虽然第一部分是正确的,但这并不是这里真正的核心问题。]


答案是“0E-59”等于 0。回想一下,BigDecimal 是未缩放值和十进制缩放因子的组合:

System.out.println(b1.unscaledValue());
System.out.println(b1.scale());

显示:

0
59

如预期的那样,未缩放的值 0。 “奇怪”的比例值只是 0.01 的非精确浮点表示的十进制扩展的产物:

System.out.println(b2.unscaledValue());
System.out.println(b2.scale());

显示:

1000000000000000020816681711721685132943093776702880859375
59

下一个明显的问题是,为什么 BigDecimal.toString 为了方便起见不将 b1 显示为“0”?答案是字符串表示需要明确。来自Javadoc for toString :

There is a one-to-one mapping between the distinguishable BigDecimal values and the result of this conversion. That is, every distinguishable BigDecimal value (unscaled value and scale) has a unique string representation as a result of using toString. If that string representation is converted back to a BigDecimal using the BigDecimal(String) constructor, then the original value will be recovered.

如果它只显示“0”,那么您将无法返回到这个确切的 BigDecimal 对象。

关于java BigDecimal 减法失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15428630/

相关文章:

java - 如果使用 double 将一种货币值与另一种货币值相互转换,可能会损失的最大精度是多少?

java - 获取Gradle守护程序以在特定的Java版本上运行

java - 通过套接字发送匿名类? (Java 中的对象..流)

java - 从其他类调用时 Getter 返回 0

java - 无法在 Gauge 中解析动态参数

java - 带舍入值的大十进制转换

java - BigDecimal 行为的差异

java - BigDecimal.ZERO 与新的 BigDecimal(0)。使用哪个,为什么?

java - 更新struts2中迭代器标签的值

java - 除法后获取数字中的所有小数位