【问题标题】:Java double comparing vs. String comparingJava 双重比较与字符串比较
【发布时间】:2015-03-10 19:31:09
【问题描述】:

我遇到了一些旧的遗留代码,如下所示:

s1 = Double.toString(dbVal1);
s2 = Double.toString(dbVal2);
if (s1.compareTo(s2)!=0)
{
    return false;
}
return true;

其中dbVal1dbVal2 都是双精度值。

我在分析时发现了这一点,toString 方法调用占用了相当多的 CPU 时间。有什么理由我不能用 1 或 2 替换它吗?如果是这样,有什么区别/哪个更好?

1.

return dbVal1 == dbVal2;

2.

return Double.compare(dbVal1,dbVal2) == 0;

【问题讨论】:

  • 看来你可以......那个字符串演员有什么理由吗??
  • 也许,出于某种原因,他们想要doubles 上的字典顺序?
  • 这就是我要删除的内容,它会导致很多速度变慢,但由于某种我想不出的原因,我不知道是否有必要。
  • @kooker 词典顺序仅与 < / > 相关。 compare() </> 0。在这里,我们只检查== resp。 == 0,所以顺序不相关。
  • 我猜原来的程序员试图避免舍入错误?看看这个答案:stackoverflow.com/questions/8081827/…

标签: java compare double


【解决方案1】:

Double 类提供了一个compare 方法,它将NaN 视为相等。我已经测试了几个有趣的案例,并且在每个案例中都给出了与更间接的 String 方法相同的结果:

public class Test {
  public static void main(String[] args) {
    testit(0.0,0.0);
    testit(0.0, -0.0);
    testit(Double.NaN, Double.NaN);
    testit(Double.NaN, 3.0);
    testit(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    testit(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
  }

  private static void testit(double a, double b) {
    boolean doubleEquals = (a == b);
    boolean doubleCompare = Double.compare(a, b) == 0;
    boolean stringCompare = Double.toString(a).compareTo(Double.toString(b)) == 0;
    if(doubleCompare != stringCompare){
      System.out.print("* ");
    }
    System.out.println("a=" + a + " b=" + b + " double == " + doubleEquals
        + " Double compare " + doubleCompare + " String compare "
        + stringCompare);
  }
}

输出:

a=0.0 b=0.0 double == true Double compare true String compare true
a=0.0 b=-0.0 double == true Double compare false String compare false
a=NaN b=NaN double == false Double compare true String compare true
a=NaN b=3.0 double == false Double compare false String compare false
a=Infinity b=Infinity double == true Double compare true String compare true
a=-Infinity b=-Infinity double == true Double compare true String compare true

【讨论】:

  • 谢谢!我要用 Double.compare 替换 toString 比较
【解决方案2】:

通常,double 值的比较方式是它们的绝对差值在一定范围内。

这是因为doubles 的内部表示方式以及可能出现的舍入误差,具体取决于值的计算方式。

如果您可以绝对确保此类错误对您来说不是问题,那么直接比较它们也很有用。

在字符串域中进行比较对我来说似乎没有用。

【讨论】:

    【解决方案3】:

    dbVal1 == dbVal2String version 不同,因为 NaN。

    double a = 0.0 / 0.0;
    double b = 0.0 / 0.0;
    System.out.println(a == b);    // false
    System.out.println(Double.toString(a).equals(Double.toString(b)));    // true
    

    我认为编写此代码的人希望 NaN 等于 NaN。

    【讨论】:

    • 我只是在尝试测试时看到了这个案例。但 Double.compare(double, double) 似乎使这项工作。有什么理由不使用这种方法?
    • @AndrewWirtz 你是对的。我只表明a == bString 版本不同。我已经相应地编辑了我的答案。我需要考虑Double.compare()
    • 别忘了0.0-0.0
    • @Marco13 还有很多事情要考虑,Infinity-Infinity 也是如此。我认为Double.compare(a, b) == 0 始终与Double.toString(a).equals(Double.toString(b)) 相同。不过,我不想在答案中肯定地断言,
    • +/-Infinity 应该不是问题。我想不出任何其他行为不同的情况(实际上尝试了一些接近MAX_VALUE 等的边界情况)。然而,无论如何,将双打作为字符串进行比较是一个可怕的想法,所以我们希望这些边界情况与提问者无关。
    【解决方案4】:

    当然,最快的方法是保留 double 变量并对其进行比较。自动装箱、使用方法、if-else 对 CPU 来说都是不必要的负担。

    【讨论】:

    • 在调用 static int compare(double d1, double d2) 时,我们没有自动装箱的情况...
    • @glglgl 我们在代码中没有明确的 if-else。这只是“供您参考”的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 2014-11-11
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多