我尝试了以下代码。但在使用 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 distinguishableBigDecimal
value (unscaled value and scale) has a unique string representation as a result of usingtoString
. If that string representation is converted back to aBigDecimal
using theBigDecimal(String)
constructor, then the original value will be recovered.
如果它只显示“0
”,那么您将无法返回到这个确切的 BigDecimal
对象。
关于java BigDecimal 减法失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15428630/