Java 双重比较与字符串比较
Java double comparing vs. String comparing
我遇到了一些旧的遗留代码,如下所示:
s1 = Double.toString(dbVal1);
s2 = Double.toString(dbVal2);
if (s1.compareTo(s2)!=0)
{
return false;
}
return true;
其中 dbVal1
和 dbVal2
都是双精度值。
我在分析时发现了这一点,toString
方法调用占用了相当多的 CPU 时间。有什么理由我不能用 1 或 2 替换它吗?如果是这样,有什么区别/哪个更好?
1.
return dbVal1 == dbVal2;
2.
return Double.compare(dbVal1,dbVal2) == 0;
当然,最快的方法是让 double
变量保持原样并进行比较。自动装箱、使用方法、if-else 对 CPU.
都是不必要的负担
通常,double
值的比较方式是它们的绝对差值在一定范围内。
这是因为 double
的内部表示方式以及可能出现的舍入误差,具体取决于值的计算方式。
如果您可以绝对确保此类错误在您的情况下不是问题,那么直接比较它们也很有用。
在字符串域中进行比较对我来说似乎没有用。
由于 NaN,dbVal1 == dbVal2
与 String version
不同。
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。
class 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
我遇到了一些旧的遗留代码,如下所示:
s1 = Double.toString(dbVal1);
s2 = Double.toString(dbVal2);
if (s1.compareTo(s2)!=0)
{
return false;
}
return true;
其中 dbVal1
和 dbVal2
都是双精度值。
我在分析时发现了这一点,toString
方法调用占用了相当多的 CPU 时间。有什么理由我不能用 1 或 2 替换它吗?如果是这样,有什么区别/哪个更好?
1.
return dbVal1 == dbVal2;
2.
return Double.compare(dbVal1,dbVal2) == 0;
当然,最快的方法是让 double
变量保持原样并进行比较。自动装箱、使用方法、if-else 对 CPU.
通常,double
值的比较方式是它们的绝对差值在一定范围内。
这是因为 double
的内部表示方式以及可能出现的舍入误差,具体取决于值的计算方式。
如果您可以绝对确保此类错误在您的情况下不是问题,那么直接比较它们也很有用。
在字符串域中进行比较对我来说似乎没有用。
dbVal1 == dbVal2
与 String version
不同。
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。
class 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