Are we safe to use floats as loop-counters and to increment/decrement them by fractional amounts at each iteration,like in the seemingly risk-free program below?Of course I know that using floats as operands for the == operator is a dumb thing to do.But what's wrong with using floats as operands for other comparison operations for "normal" purposes? By "normal" I mean that,well,even though floats may not be the exact numerical representation of the number,but isn't a variation like 0.000000001
irrelevant and can be ignored in most cases? (For example in the following program that isn't even apparent)
But that said, here is my apprehension.Suppose the representation isn't exact and 5.0 is actually 4.999999.So as we go on decrementing by 0.5 at each iteration,the last comparison with 0 may turn out false and the loop may exit due to a difference of 0.000001,and the last line of current output will not be displayed. I hope you are getting my drift.How wrong am I?
#include<stdio.h>
int main(void)
{
float f;
for(f=5.0;f>=0;f-=0.5)
printf("%f\n",f);
}
Output:
5.000000
4.500000
4.000000
3.500000
3.000000
2.500000
2.000000
1.500000
1.000000
0.500000
0.000000
No, it's not safe, for the reasons given in your very question. Consider this:
#include<stdio.h>
int main(void) {
float f = 1.0;
for(;f>0;f-=0.1)
printf("%f\n",f);
return 0;
}
This example seems to work quite ok when f
is initialized by 1.0
. But change this to 3.0 - and things start to get way more interesting pretty soon:
2.600000
2.500000
2.400001
...
0.000001
... leading to the infamous 'off-by-one' failure.
You think that you might be safe with >=
instead of >
? Think again:
float f = 5.0;
for(;f>=1;f-=0.4)
printf("%f\n",f);
...
3.400000
3.000000
2.599999
2.199999
1.799999
1.399999
... and off-by-one we go again (as 0.99999
is less than 1).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With