你能否将浮点值精确地与零进行比较?

我知道我们无法使用==来比较2个浮点值。 我们只能比较它们是否在彼此的某个区间内。 我知道

if(val == 0.512) 

由于浮点计算和转换为二进制所固有的错误而错误,应该是错误的

 if (val in (0.512-epsilon, 0.512+epsilon)) 

但是0特别吗? 我们可以将浮点数精确地比较为0吗? 甚至那是不正确的? 特别是在C#和Java的上下文中?

 double val = 0; val = getVal(); if(val == 0) 

尽管0具有精确的表示,但您不能依赖使用浮点数计算的结果正好为0.正如您所指出的,这是由于浮点计算和转换问题。

因此,您应该针对您的容差epsilon测试0。

如果指定了变量零,则可以比较为零。 如果你从例如零。 减法你仍然可以获得接近于零的非常小的数字。 例如:0.1-0.1可以评估为1e-9之类的东西。

使用容差 / ephsilon方法。

我刚刚在Java中评估了以下内容,它在数学上导致零:

 1.0/5.0 + 1.0/5.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0 

实际上得到了

 2.7755575615628914E-17 

为了与错误进行比较,您需要的是。

 // compare a and b with an ERR error. if (Math.abs(a - b) <= ERR) 

与0比较

 // compare a and 0 with an ERR error. if (Math.abs(a) <= ERR) 

因为零确实具有精确表示,所以可以将值==与零进行比较。 如果您正在测试的变量是由赋值设置的,或者是从输入的值(如示例中的getVal?)设置的,那么它很容易为零。 但如果它是计算的结果,那么它恰好为零的可能性非常小。 这变得更糟,因为像0.2这样的普通小数部分在浮点中没有精确的表示。 这就是为什么最好使用epsilon。

我仍然建议遵循容差惯用语,而不是完全与零比较。

我一般认为你不能 – getVal()中发生的计算可能在逻辑上导致零,但这并不意味着它将返回零。 如果你明确地返回一个零来表示某种情况,那么比较应该总是有效,但我不认为这是最好的做法。 我修改函数以返回状态代码并传递值由ref改变。

在任何非平凡的情况下,您应该只使用容差方法。 如上所述,零比较仅在您实际将其分配为零时才是准确的。

在不重复其他人所说的内容的情况下,我只想强调使用容差方法更具未来性的事实。 您曾经认为的一个简单的任务可能涉及以后的实际算术。 使用裸露的比较使得以后进行调试变得非常模糊。