Reputation: 4153
If foo is of float type, is the following expression valid/recommended?
(0.0f == foo * float(0))
Will it have the expected (mathematical) value regardless of foo's value?
Does the C++ standard defines the behavior or is it implementation specific?
Upvotes: 6
Views: 15220
Reputation: 346240
With that particular statement, you can be pretty sure the result will be 0
and the comparison be true
- I don't think the C++ standard actually prescribes it, but any reasonable implementation of floating point types will have 0
work like that.
However, for most other calculations, the result cannot be expected to be exactly equal to a literal of the mathematically correct result:
Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and instead I get a weird result like 0.30000000000000004?
Because internally, computers use a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.
When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens.
Read The Floating-Point Guide for detailed explanations and how to do comparisons with expected values correctly.
Upvotes: 1
Reputation: 62323
AFAIK, It won't necessarily, it could also end up very close to 0.
It is generally best to compare against an epsilon. I use a function like this for doing such comparisons:
float EpsilonEqual( float a, float b, float epsilon )
{
return fabsf( a - b ) < epsilon;
}
Upvotes: 2
Reputation: 145194
NaNs and Infinites can screw up such comparisions, as others have already mentioned.
However, there is further pitfall: in C++ you can not rely on a compile time expression of float type, comparing equal to the same expression evaluated at run time.
The reason for that is that C++ allows extended precision for fp computations, in any willy-nilly way. Example:
#include <iostream>
// This provides sufficent obfuscation so that g++ doesn't just inline results.
bool obfuscatedTrue() { return true; }
int main()
{
using namespace std;
double const a = (obfuscatedTrue()? 3.0 : 0.3);
double const b = (obfuscatedTrue()? 7.0 : 0.7);
double const c = a/b;
cout << (c == a/b? "OK." : "\"Wrong\" comparision result.") << endl;
}
Results with one particular compiler:
C:\test> g++ --version | find "++"
g++ (TDM-2 mingw32) 4.4.1
C:\test> g++ fp_comparision_problem.cpp & a
"Wrong" comparision result.
C:\test> g++ -O fp_comparision_problem.cpp & a
OK.
C:\test> _
Cheers & hth.,
– Alf
Upvotes: 2
Reputation: 33
I just read this article in msdn about the /fp option in VisualStudio link text
Expression optimizations that are invalid for special values (NaN, +infinity, -infinity, +0, -0) will not be allowed. The optimizations x-x => 0, x*0 => 0, x-0 => x, x+0 => x, and 0-x => -x are all invalid for various reasons (see IEEE 754 and the C99 standard).
Upvotes: 0
Reputation: 44794
Well, first off it isn't really a matter of the C++ standard. Rather what is at issue is your floating-point model standard (most likely IEEE).
For IEEE floats, that is probably safe, as float(0)
should result in the same number as 0.0f, and that multiplied by any other number should also be 0.0f.
What isn't really safe is doing other floating point ops (eg: adds and subtracts with non-whole numbers) and checking them against 0.0f.
Upvotes: 3