Java 检查双重身份是否安全?
我有以下代码:Java 检查双重身份是否安全?,java,floating-point,Java,Floating Point,我有以下代码: double x = 0; { ...do stuff ...} if(x == 0){ } 我一直被教导,你不应该检查浮点数是否相等。检查它是否等于零有什么不同吗?不应该检查浮点数是否相等的原因是浮点数不是完全精确的——有些数字在存储中存在不精确性,例如那些延伸到尾数太远的数字和重复的小数(请注意,我说的是基数2中的重复小数)。您可以将这种不精确性视为“向下舍入”。超出浮点数精度的数字会被截断,实际上是向下舍入 如果它没有改变,它将保持相等。但是,如果你稍微改变它,你可
double x = 0;
{ ...do stuff ...}
if(x == 0){
}
我一直被教导,你不应该检查浮点数是否相等。检查它是否等于零有什么不同吗?不应该检查浮点数是否相等的原因是浮点数不是完全精确的——有些数字在存储中存在不精确性,例如那些延伸到尾数太远的数字和重复的小数(请注意,我说的是基数2中的重复小数)。您可以将这种不精确性视为“向下舍入”。超出浮点数精度的数字会被截断,实际上是向下舍入 如果它没有改变,它将保持相等。但是,如果你稍微改变它,你可能不应该使用相等,而应该使用像
(x<0.0001&&x>-.0001)
这样的范围
简而言之:只要你不是在一个很小的级别上玩x,就可以了。如果你试图捕捉的0是初始化时设置的原始0,这是安全的。但是,如果你期望数学运算得到一个0,这是不安全的。你仍然不应该检查它是否等于零。只要检查它是否接近零就可以了。
private final static double EPSILON = 0.00001;
if (x + EPSILON > 0 && x - EPSILON < 0){
...
}
private final static double EPSILON=0.00001;
如果(x+ε>0&&x-ε<0){
...
}
如果您自己设置它,并希望查看它是否发生过更改,您可以安全地检查是否相等(如使用sentinel值),尽管NaN在这方面更安全
float x=Float.NaN;
{
//some code that may or may not set x
}
if(Float.isNaN(x))//it never got set
double有正零和负零。
==
在正零和负零之间返回false。另外,=
在两个nan之间返回false。我不明白,如果你将x初始化为0,为什么检查0是否是一个有效值不好?当你开始达到li时,0是一个双浮点数的大量舍入值mits。同样的原因,如果你有3位数字以10为基数,你有.004,除以3,你期望.001,但谁知道会发生什么。托马斯的修正:从技术上讲,这不是四舍五入,而是由于精度有限和浮点数的二进制性质而导致的不准确。有人应该总结一下这个问题的所有答案。这不是四舍五入事情是这样的,但由于浮点数的表示,无法存储某些数字。0可以用浮点数精确表示,但并非所有值都可以。例如,0.1必须近似。@Thomas Rounding down.3/2
的原因与1
相同,不是舍入。IEEE flo中的不精确性点表示法。与舍入完全无关。同样的@Thomas。你会说3/2
是1
,因为“整数表示法不精确”?参见第173页,或者是的,它与舍入完全无关。除了它是(甚至由@Thomas链接)。您不应使用绝对值,而应使用相对值。例如,if(value>=target*(1-ε)&&value@HovercraftFullOfEels这仅在目标为正时有效。当您想从数学运算中比较0时,正确的方法应该是什么?您错了。负零比较等于正零。这是Java遵循的IEEE-794标准所要求的。