Can you compare floating point values exactly to zero?
I know we can't开发者_如何学编程 compare 2 floating point values using ==. We can only compare they are within some interval of each other. I know
if(val == 0.512)
is wrong due to errors inherent in floating point calculations and conversion to binary and should be
if (val in (0.512-epsilon, 0.512+epsilon))
But is 0 special? Can we compare floats exactly to 0? Or even that is incorrect? Particularly in the context of C# and Java?
double val = 0;
val = getVal();
if(val == 0)
Even though 0 has an exact representation, you can't rely on the result of a calculation using floats to be exactly 0. As you noted, this is due to floating point calculation and conversion issues.
So, you should test for 0 against your tolerance epsilon.
You can compare to zero if you assigned that variable zero. If you get zero from eg. a subtraction you can still get a very small number close to zero. eg.: 0.1-0.1 may evalute to something like 1e-9.
Use the tolerance / ephsilon approach.
I just evaluated the following in Java, which mathematically results in zero:
1.0/5.0 + 1.0/5.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0
and actually got
2.7755575615628914E-17
Because zero does have an exact representation, it is possible for a value to compare == to zero. If the variable you are testing was set by an assignment, or from a value typed in (like getVal in your example?), it could easily be zero. But if it was the result of a calculation, the chances of it being exactly zero are very small. This is made worse because ordinary decimal fractions like 0.2 do not have an exact representation in floating point. That's why it's best to use epsilon.
For comparison with err all you need to is.
// compare a and b with an ERR error.
if (Math.abs(a - b) <= ERR)
To compare with 0
// compare a and 0 with an ERR error.
if (Math.abs(a) <= ERR)
I would still recommend following the tolerance idiom and not compare to zero exactly.
I don't think you can in general - the calculation that occurs in getVal() might logically result in zero but that dosn't mean it will return zero. If you explicilty return a zero to indicate some condition then the compare should always work but I don't think it would be best practice. I'd modify the function to return a status code and pass the value to be changed byref.
In any non-trivial situation, you should really only use the tolerance approach. As noted, zero comparison is only accurate when you actually assigned it to zero.
Without repeating what other have said, I just want to emphasize the fact that using the tolerance approach is more future proof. What you once think is a simple assignment may involve actual arithmetic later. Using a naked comparison makes it painfully obscure to debug at a later date.
精彩评论