Ric*_*ard 58 java rounding-error bigdecimal numerical-analysis
我正在使用BigDecimal进行简单的乘法运算,并且在乘以零时我发现了一些奇怪的行为(在这个用例中乘以零是正确的).
基本数学告诉我,任何乘以零的数字都将等于零(参见:零产品属性和乘法属性)
但是,以下代码将始终失败并出现相同的错误:
assertEquals(new BigDecimal(0), new BigDecimal(22.3).multiply(new BigDecimal(0)));
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)java.lang.AssertionError: Expected :0 Actual :0E-48
这是BigDecimal的不准确,还是我在某处遗漏了数学的一些利基分支?
注意:在IntelliJ 11中运行的JDK 1.6.0_27
Kep*_*pil 84
您不能使用该equals()方法进行比较BigDecimals,就像这个断言一样.那是因为这个等于函数会比较比例.如果比例不同,equals()则返回false,即使它们在数学上是相同的数字.
但是,你可以用compareTo()你想做的事情:
正如@assylias指出的那样,您还应该使用new BigDecimal("22.3")构造函数来避免双精度问题.
BigDecimal expected = BigDecimal.ZERO;
BigDecimal actual = new BigDecimal("22.3").multiply(BigDecimal.ZERO);
assertEquals(0, expected.compareTo(actual));
Run Code Online (Sandbox Code Playgroud)
还有一个名为的方法signum(),它返回-1,0或1表示负数,零和正数.所以你也可以测试零
assertEquals(0, actual.signum());
Run Code Online (Sandbox Code Playgroud)
ass*_*ias 47
您的代码有两个问题:
new BigDecimal("22.3")而不是双构造函数new BigDecimal(22.3)来避免双精度问题换句话说,以下代码(正确使用compareTo)仍然返回false:
BigDecimal bd = new BigDecimal(0.1).multiply(new BigDecimal(10));
System.out.println(bd.compareTo(BigDecimal.ONE) == 0);
Run Code Online (Sandbox Code Playgroud)
因为 0.1d * 10d != 1
Jig*_*shi 20
equals()上BigDecimal检查的内部状态BigDecimal进行比较
请参阅以下代码
public boolean equals(Object x) {
if (!(x instanceof BigDecimal))
return false;
BigDecimal xDec = (BigDecimal) x;
if (x == this)
return true;
if (scale != xDec.scale)
return false;
long s = this.intCompact;
long xs = xDec.intCompact;
if (s != INFLATED) {
if (xs == INFLATED)
xs = compactValFor(xDec.intVal);
return xs == s;
} else if (xs != INFLATED)
return xs == compactValFor(this.intVal);
return this.inflate().equals(xDec.inflate());
}
Run Code Online (Sandbox Code Playgroud)
如果你想比较使用的值 compareTo()
将您的代码更改为
assertEquals(0 , new BigDecimal(0).compareTo(new BigDecimal(22.3).multiply(new BigDecimal(0)));
Run Code Online (Sandbox Code Playgroud)
更新:
使用构造函数将String作为BigDecimal的参数,以便精确检查下面的相关链接
另见
| 归档时间: |
|
| 查看次数: |
4377 次 |
| 最近记录: |