如何比较BigDecimal的近似值?

3

我有这段代码:

BigDecimal d = ...;
if (d.compareTo(Expression.PI) == 0) {
    //do something
}

其中Expression.PI是保留到小数点后100位的圆周率。

但我不需要比较d是否与圆周率相等,只需要比较前20位。换句话说,如何检查d是否大致等于圆周率?

我尝试过

Expression.PI.setScale(20, RoundingMode.HALF_UP).compareTo(d.setScale(20, RoundingMode.HALF_UP)) == 0;

并且。
Expression.PI.setScale(20, RoundingMode.HALF_UP).compareTo(d) == 0;

但是这两种方法似乎都不起作用。我在这里做错了什么吗?

你能提供一些数字的例子吗?这些数字在你预期中应该是有效的,但实际上却没有按照你的预期工作吗? - lucasvw
举个例子,如果我有一个保留20位小数的圆周率数字。那是不行的,因为Expression.PI已经保留了100位小数。 - leonz
你确定 d 等于精确到小数点后 20 位的圆周率吗?首先,很难相信你需要那么高的精度。你可以尝试四舍五入到 5 位,看看会发生什么。 - lucasvw
这只是一个例子,以澄清问题。而问题不在于我需要多少精度。无论如何,这并不重要,重要的是解决方法。一旦我找到了解决办法,我就可以简单地改变精度。 - leonz
1
但我非常确定你所拥有的就是做这件事情的方法。这就是为什么我对你尝试过的确切值感到好奇。 - lucasvw
嗯,那么问题可能在我的代码的其他地方。谢谢。 - leonz
2个回答

6

正如lucasvw在评论中提到的那样,我认为您已经做得正确,但可能存在'd'值的问题。以下是一个测试类,展示了正确的结果。

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalTest {

public static void main(String args[]) {
    BigDecimal PI = new BigDecimal("3.14159265358979323846264338327950288419");
    BigDecimal otherValue = new BigDecimal("3.14159");

    boolean test = PI.setScale(5, RoundingMode.HALF_UP).compareTo(otherValue) == 0;

    System.out.println("compareTo: " + test);
}
}

1
public static final boolean isWithinTolerance(final BigDecimal bigDecimal1, final BigDecimal bigDecimal2, final BigDecimal tolerance)
{
    if (bigDecimal1 == null || bigDecimal2 == null || tolerance == null)
    {
        return false;
    }

    final BigDecimal diff = bigDecimal1.abs().subtract(bigDecimal2.abs()).abs();

    return diff.compareTo(tolerance) < 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接