我想检查一个double
是小于、等于还是大于另一个double
。尽管我读了很多关于floats
和doubles
由于计算机在二进制级别如何计算而无法精确比较的信息,但到目前为止,使用简单的二进制运算符就像一个魅力。我用几十个不同的数字测试了它,到目前为止,它甚至没有让我失望过一次。
那么在我的情况下,这样比较它们真的有问题吗?如果有 - 为什么我找不到它以及如何修复它?
编辑:我知道如果我决定比较它们,0.1 + 0.2 != 0.3
。问题是 - 我想简单地比较两个固定doubles
.我不必比较0.1 + 0.2
和0.3
.我最多只能比较0.3
和0.3
。或者0.4
和0.3
.类似的东西。我真的需要使用BigDecimal,epsilon或其他任何东西吗?
double
s 是十进制数的离散表示形式。这意味着并非所有数字都可以用双精度表示。
例如,double
无法准确地表示一些非常大的数字,在这种情况下,它们被"四舍五入"到最接近的可用双精度。例如,请参阅:
public static void main(String[] args) {
double d1 = 1e50;
double d2 = d1 + 1;
System.out.println(d2 > d1); //false
System.out.println(d2 == d1); //true
}
下面是使用 float 可能导致错误的示例。
System.out.println(1.0 - 0.2 - 0.3 - 0.4 - 0.1); // Is not 0.0
如果需要任意精度的十进制数,请使用 BigDecimal
。
<
和>
运算符不是问题。
==
运算符会对任何真实数据产生问题。 所以你还没有遇到问题? 好吧,你可以在雷暴期间在高尔夫球场上跑来跑去,在头上挥舞着球杆,也不会被闪电击中。 并不意味着你不会。
double
的 精确可比性。问题出现主要有两个原因
- 许多人认为数学与
double
的数学与实数的数学相同。它没有。许多关于什么事物应该完全相等的假设不容易(或根本不)从实数转化为double
。 - "有趣的事情",例如扩展精度不可预测地激活(使用
strictfp
)
像往常一样,其他答案是错误的。double
并不"表示"一系列数字(你可以假装它们代表,但最终double
只有一个确切的值,并且不知道它意味着表示什么样的"范围")。表明double
的相等可以产生"有趣的结果"的答案是正确的,因为结果是"有趣的",但问题在于预期结果,而不是结果本身。如果你期望正确的东西,那里没有问题。