【发布时间】:2014-09-29 09:18:40
【问题描述】:
我想向那些在 Java 中使用原始 double 平等有更多经验的人提出一些建议。由于可能存在舍入错误,将 d1 == d2 用于两个双精度 d1 和 d2 是不够的。
我的问题是:
Java 的
Double.compare(d1,d2) == 0是否在某种程度上处理了舍入错误?如1.7 documentation 中所述,如果d1在数值上等于d2,则返回值0。有人确定他们所说的数字相等到底是什么意思吗?对某个 delta 值使用相对误差计算,您会推荐一个通用的(不是特定于应用程序的)delta 值吗?请参阅下面的示例。
下面是一个通用函数,用于在考虑相对误差的情况下检查相等性。您建议delta 的什么值来捕获来自简单操作+、-、/、* 操作的大部分舍入错误?
public static boolean isEqual(double d1, double d2) {
return d1 == d2 || isRelativelyEqual(d1,d2);
}
private static boolean isRelativelyEqual(double d1, double d2) {
return delta > Math.abs(d1- d2) / Math.max(Math.abs(d1), Math.abs(d2));
}
【问题讨论】:
-
您的
isRelativelyEqual是对问题进行全面攻击的正确方法(除了 NaN 问题)。您可以根据浮点格式的精度位数选择delta,对于双精度,有效的 53 位或 16 位十进制数字,以及您想要的“接近”程度。或者,您可以在数字上使用doubleToLongBits,“向上取整”分数以消除 1-3 个分数位,然后比较是否相等。
标签: java double double-precision