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

时间:2010-03-04 10:55:20

标签: c# java floating-point

我知道我们无法使用==来比较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)

8 个答案:

答案 0 :(得分:17)

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

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

答案 1 :(得分:13)

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

答案 2 :(得分:13)

使用容差 / 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

答案 3 :(得分:4)

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

// 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)

答案 4 :(得分:3)

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

答案 5 :(得分:2)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

不重复其他人的说法,我只想强调使用容忍方法更加强烈“未来证明这一事实。您曾经认为的一个简单的任务可能涉及以后的实际算术。使用裸露的比较会使以后的调试变得非常模糊。