Testing floating point numbers for equality In general I know it's dangerous to test floating point numbers for being equal to a known value because of the inherent inaccuracy of the representation for some values.
mutabled
It's the same problem, when you assign a floating point number you don't know what it is stored as.
Martin Beckett
> needless casting overhead in tight loops
Matthew Lock
>Except by coincidence the value stored as 1.0 in floating point is no >more likely to be exactly 1.0 than storing 1.1234567890 is exactly >that.
a2800276
If you're only testing for those three values you can just use: x!=0, x>0, x<0 and you'll be fine.
John Q Tester
>You could also use constants (YES NO MAYBE, GT EQ LT) to >ensure they're exactly the same value.
Martin Beckett
I believe that 1.0, 0.0 and -1.0 (and indeed any integers, up to a certain limit) will always be stored as exact values in floating point. So if you really are only assigning these values once, then you shouldn't have any problems - but can you guarantee that will be true in the long term?
Matthew Wilson
The solution I like best is the one that suggested comparing to zero. Assign the values -1.0, 0, 1.0. Then, compare them to zero
AllanL5
Or, you could use interval arithmetic and not have to worry about precision problems anymore.
sir_flexalot
I don't know of any floating-point system ever used in which the numbers 0 and +-1 weren't represented exactly. If your platform is using IEEE floating-point (which it is) then those values are guaranteed to be exact. So is any number of the form integer / 2^k where k and the length of the integer aren't too large.
Gareth McCaughan
Theoretically, it would be possible to implement floating point data that did not store an integer as an exact value, but I have never heard of any implementation that did such a thing. Integers are stored as exact values in floating point up to the number of digits that fit in the mantissa. A double can store more digits than a four byte integer and are useful for storing large integers.
mackinac
See here for some details on the IEEE format for double-precision floating point numbers: http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html .
Matthew Morris
Use an aggregated class (System.Decimal) ... Compare against 1.0M?
Anon
Ok, forgive my stupidity here, but how is it that a value of 1.0 can be stored as "not quite" 1.0 in a FP variable? I've never read anything like that.
muppet from madebymonkeys.net
Also keep an eye on how the values are getting set. If they are assgned from constants you are taking a pretty small risk. But if those values come from any kind of a calculation...
Tom H
Do NOT use == with floating point!
Dennis Atkins
muppet,
Dennis Atkins
Then again that's only if they were just put there. Pass them around a little and that 1.0 becomes 0.999999999999987 before you know it.
Dennis Atkins
ok, but how? How can the value of 1.0 change if it is only being assigned once, and then compared against other values or passed to other functions?
muppet from madebymonkeys.net
It's generally very good advice not to compare floating-point numbers with ==, but *in this particular situation* there's nothing wrong with it. The fact that IEEE floating point has signed zeroes doesn't cause any problems here; -0 and +0 compare equal. And the second part of Dennis's advice ("use an epsilon and do all floating-point comparisons through a set of functions") needs to be applied with caution; what it *doesn't* mean (or, at least, shouldn't) is to define some universal value epsilon and replace x==y with fabs(x-y)<=epsilon everywhere. If you do that, then you will lose when x and y are either very large or very small. So you could use a relative value for epsilon instead, and replace x==y with fabs(x-y) <= epsilon*(fabs(x)+fabs(y)), but that's not right for all situations either and it's quite expensive. The only reliable advice, I'm afraid is: Understand what you're doing. Then it's easy. Well, easier. :-)
Gareth McCaughan
In retrospect, I think I'm very glad that I never expended the effort to learn C/C++ completely. I stopped when I hit Windows GUI programming. :P
muppet from madebymonkeys.net
Subtract the two numbers and see if the result is less than some reasonable error.
MilesArcher
Not a joke. Consider that case when, as it gets passed down a calling chain with no apparent operations performed, it gets downcast to be a float and then upcast to be a double, etc. Before you know it it's turned into a different number when it gets compared to the original and you didn't do anything to it. This is not going to happen with powers of 2 but I have seen this problem occur and it's why I will grep on 'float' and tear that out of everywhere and replace it with double. Even so, you can still get stuck if you are relying on library functions to use doubles anid not floats internally.
Dennis Atkins
Oh sorrt, you did mention that in your pedant section. i should have read the whole post. My apologies.
Dennis Atkins
muppet,
Bill Tomlinson
Small intro:
VPC
That's got to be the most perverse code I've ever seen. :-)
Chris Tavares
>>With normal values for money and similar values
John C.
(by "float" above, I also mean "double" or any other fp type)
John C.
I'd like to know the mechanism (bitwise) by which (double)1.0 is not equal to exactly (float)1.0. I have never heard of that, doesn't seem reasonable really.
Roose
I can't remember the exact bug I ran into once, but it was some problem caused by 6400 being represented exactly, but 1/6400 could not. Something to the effect of taking a number and multiplying it by 6400, truncating it, and then multiplying it by 1/6400, and subtracting it from the original number and ended up with a remainder greater than 1/6400th. I'm not sure that is exactly how it worked, but because 1/6400th could not be represented exactly, multiplying and in effect dividing by the same number did not bring me back to the same number, and the truncate in there brought it down a whole int value.
Keith Wright
ROFLMAO!
Ian
unsigned 32bit integers cannot handle more than ~$42M bucks which makes them unsuitable for real world lottery or banking accountancy where you track every cent.
macEroni
yeah, its getting late
john pollock
Fog Creek Home |