当前位置: 首页 > 知识库问答 >
问题:

BigDecimal乘以零

戚默
2023-03-14

我正在使用BigDecimal执行简单的乘法运算,并且在乘以零时发现了一些奇怪的行为(在此用例中乘以零是正确的)。

基础数学告诉我,任何乘以零的东西都等于零(参见:零积性质和乘法性质)

但是,以下代码将始终以相同的错误失败:

assertEquals(new BigDecimal(0), new BigDecimal(22.3).multiply(new BigDecimal(0)));
java.lang.AssertionError: 
Expected :0
Actual   :0E-48

这是BigDecimal的错误还是我在某个地方遗漏了一些数学的利基分支?

注:JDK 1.6.0\u 27在IntelliJ 11中运行

共有3个答案

吉岳
2023-03-14

打开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());
}

如果要比较值,请使用compareTo()

将代码更改为

assertEquals(0 , new BigDecimal(0).compareTo(new BigDecimal(22.3).multiply(new BigDecimal(0)));

更新:

使用将String作为BigDecimal参数的构造函数以提高精度检查以下相关链接

另请参见

  • 评估100*2.55的值时得到错误的结果
盛嘉
2023-03-14

您的代码有两个问题:

  • 正如其他答案所建议的那样,您应该将BigDecimal与compareTo进行比较,而不是与equals进行比较
  • 但您还应该使用字符串构造函数:new bigdecime(“22.3”)而不是双构造函数new bigdecime(22.3),以避免双精度问题

换句话说,以下代码(正确使用compareTo)仍返回false:

BigDecimal bd = new BigDecimal(0.1).multiply(new BigDecimal(10));
System.out.println(bd.compareTo(BigDecimal.ONE) == 0);

因为<代码>0.1d*10d!=1

蔡辰钊
2023-03-14

您不能像此断言那样使用equals()方法来比较大小数。这是因为这个equals函数将比较刻度。如果刻度不同,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));

还有一个名为signum()的方法,它为负、零和正返回-1、0或1。所以你也可以用

assertEquals(0, actual.signum());
 类似资料:
  • 描述 (Description) java.math.BigDecimal.subtract(BigDecimal subtrahend)返回一个BigDecimal,其值为(this - subtrahend),其标度为max(this.scale(),subtrahend.scale())。 声明 (Declaration) 以下是java.math.BigDecimal.subtract()

  • 描述 (Description) java.math.BigDecimal.remainder(BigDecimal divisor)方法返回一个BigDecimal,其值为(this%divisor)。 余数由this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))给出。 这不是模运算,即结果可能是负的。 声明 (D

  • 描述 (Description) java.math.BigDecimal.multiply(BigDecimal multiplicand)返回一个BigDecimal,其值为(this×multiplicand),其标度为(this.scale()+ multiplicand.scale())。 声明 (Declaration) 以下是java.math.BigDecimal.multiply

  • 描述 (Description) java.math.BigDecimal.min(BigDecimal val)返回此BigDecimal和val的最小值。 声明 (Declaration) 以下是java.math.BigDecimal.min()方法的声明。 public BigDecimal min(BigDecimal val) 参数 (Parameters) val - 要计算最大值

  • 描述 (Description) java.math.BigDecimal.max(BigDecimal val)返回此BigDecimal和val的最大值。 声明 (Declaration) 以下是java.math.BigDecimal.max()方法的声明。 public BigDecimal max(BigDecimal val) 参数 (Parameters) val - 要计算最大值

  • 描述 (Description) java.math.BigDecimal.divideToIntegralValue(BigDecimal divisor)返回一个BigDecimal,其值是向下舍入的商(this/divisor)的整数部分。 结果的首选比例是(this.scale() - divisor.scale())。 声明 (Declaration) 以下是java.math.BigD