执行检查java.lang.Double是否相等的方法



检查双值是否相等的最有效方法是什么。

我知道

double a = 0.00023d;
double b = 0.00029d;
boolean eq = (a == b);

是缓慢的。

所以我用

double epsilon = 0.00000001d;
eq = Math.abs(a - b) < epsilon;

问题是Infinitest抱怨测试花费了太多时间。这没什么大不了的(1秒上限),但它让我很好奇。

附加信息

a是硬编码的,因为它是期望值,b由计算

  // fyi: current = int, max = int
  public double getStatus()
  {
    double value = 0.0;
    if (current != 0 && max != 0)
      value = ((double) current) / max;
    return value;
  }

更新

java.lang.Double就是这样做的

public boolean equals(Object obj) {
return (obj instanceof Double)
       && (doubleToLongBits(((Double)obj).value) ==
          doubleToLongBits(value));
}

所以人们可以认为这是最好的做法。

JUnit有一种检查Double是否与给定delta"相等"的方法:
Assert.assertEquals(0.00023d, 0.00029d, 0.0001d);

请参阅本API文档。

正如评论中所指出的,JUnit实际上很可能比手动比较给定的delta慢。JUnit首先执行Double.compare(expected, actual),然后(如果不相等)执行Math.abs(expected - actual) <= delta

希望这个答案对那些没有意识到JUnit实际上为不精确的Double平等测试提供了一种方法的人仍然有用。

实际上,比较两个浮点/双精度值是否相等本身就是一种糟糕的做法,因为浮点数字会出现舍入误差。在符号数学中相等的两个数字可能与计算机不同,这取决于它们的计算方式。

最佳实践是您使用的第二个选项:Math.abs(a - b) < epsilon
我知道它可能比你想要的慢,但这是正确的方法。从应用程序的角度来看,逐位比较可能会导致两个数字被认为是不同的,即使它们是相同的(如果你手工计算,它们会相等,但由于舍入误差,它们逐位不同)。

java.lang.Double

如问题java.lang.Double.equals()调用public static long doubleToLongBits(double value),哪个

/**
 * Returns a representation of the specified floating-point value
 * according to the IEEE 754 floating-point "double
 * format" bit layout.

然后检查是否与CCD_ 11相等。(doubleToLongBits内部调用public static native long doubleToRawLongBits(double value),因此它依赖于平台)。

这里是原始类型的工作方式。

原始类型双

浮点类型为float和double,它们在概念上与IEEE二进制浮点运算标准ANSI/IEEE标准754-1985(IEEE,纽约)中规定的单精度32位和双精度64位格式IEEE 754值和运算相关联JLS-4.2.3


浮点数上的运算符的行为符合IEEE 754的规定(余数运算符除外(§15.17.3))。JLS-4.2.4


因此,最快的方法是使用基元类型,并可能根据所需的准确性执行"delta检查"。如果使用Double提供的方法无法做到这一点。

不应该使用JUnit断言方法,因为它执行更多的检查,所以最好做一些事情,比如:

boolean eq = Double.valueOf(5.0d).equals(Double.valueOf(2.0d));
Assert.assertTrue(eq);

相关内容

  • 没有找到相关文章