我希望能向更有经验的Java原始双精度浮点数相等性处理人员征求建议。由于可能存在舍入误差,使用d1 == d2
来比较两个双精度浮点数d1
和d2
是不够准确的。
我的问题如下:
Java的
Double.compare(d1,d2) == 0
是否在一定程度上处理了舍入误差?如1.7文档所述,如果d1
与d2
在数值上相等,则返回值为0
。是否有人确定他们所说的“数值上相等”具体指什么?使用相对误差计算与某个Δ值进行比较,您会推荐通用(非特定应用程序)的δ值吗?请参见下面的示例。
以下是一个通用函数,用于考虑相对误差检查相等性。您会推荐什么值的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个小数位,然后进行相等比较。 - Hot Licks