Bob Badour wrote:
> David Cressey wrote:
>
>> Here's another example of floating point errors, that's even simpler
>> than
>> the 21200 plus 2.5% example.
>>
>> int i;
>> float x = 0;
>> for (i = 1; i < 100; ++i)
>> x += 0.01;
>> x -= 1;
>> printf (x);
>>
>> I apologize if I copied the code wrong. The idea is to start with zero,
>> add one hundredth a hundred times, and subtract one. The answer is not
>> quite zero.
>>
>> Many environments will give a small error. This is such a trivial
>> example
>> that it should make all programmers shudder about using floats, unless
>> they
>> really know what they are doing.
>
>
> The code above only adds 99 times.
>
> I translated the above into C, corrected it and expanded on it. The
> naive method below ignores rounding. The aware method is aware of both
> the limitation in the representations and in the range of interest
> (chosen as 5 decimal places based on the useful precision of the float
> type.)
>
> This is such a trivial example that it should make all programmers who
> don't know what they are doing shudder.
>
> ------------>8----------------------->8-----------------
>
> #include <math.h>
> #include <stdio.h>
>
> int main() {
> int i;
> float x = 0;
> double d = 0;
>
> /* naive method */
> printf("naive\n");
> for (i = 0; i < 100; ++i)
> x += 0.01;
> x -= 1;
> printf ("%8.5f %e\n",x,x);
>
> for (i = 0; i < 100; ++i)
> d += 0.01;
> d -= 1;
> printf ("%8.5f %e\n",d,d);
>
> x = 0.01;
> x *= 100;
> x -= 1;
> printf("%8.5f %e\n",x,x);
>
> d = 0.01;
> d *= 100;
> d -= 1;
> printf("%8.5f %e\n",d,d);
>
> x = 0;
> for (i = 1; i < 100; ++i)
> x += 0.01;
> x -= 0.99;
> printf ("%8.5f %e\n",x,x);
>
> d = 0;
> for (i = 1; i < 100; ++i)
> d += 0.01;
> d -= 0.99;
> printf ("%8.5f %e\n",d,d);
>
> x = 0.99;
> d = 0.99;
> x += 0.01;
> d += 0.01;
>
> x -= 1;
> printf("%8.5f %e\n",x,x);
>
> d -= 1;
> printf("%8.5f %e\n",d,d);
>
>
> /* aware method */
> printf("aware\n");
> for (i = 0; i < 100; ++i)
> x += 0.01;
> x -= 1;
> printf ("%8.5f %e\n",floor(x*1e5+0.5)/1e5,floor(x*1e5+0.5)/1e5);
>
> for (i = 0; i < 100; ++i)
> d += 0.01;
> d -= 1;
> printf ("%8.5f %e\n",floor(d*1e5+0.5)/1e5,floor(d*1e5+0.5)/1e5);
>
> x = 0.01;
> x *= 100;
> x -= 1;
> printf ("%8.5f %e\n",floor(x*1e5+0.5)/1e5,floor(x*1e5+0.5)/1e5);
>
> d = 0.01;
> d *= 100;
> d -= 1;
> printf ("%8.5f %e\n",floor(d*1e5+0.5)/1e5,floor(d*1e5+0.5)/1e5);
>
> x = 0;
> for (i = 1; i < 100; ++i)
> x += 0.01;
> x -= 0.99;
> printf ("%8.5f %e\n",floor(x*1e5+0.5)/1e5,floor(x*1e5+0.5)/1e5);
>
> d = 0;
> for (i = 1; i < 100; ++i)
> d += 0.01;
> d -= 0.99;
> printf ("%8.5f %e\n",floor(d*1e5+0.5)/1e5,floor(d*1e5+0.5)/1e5);
>
> x = 0.99;
> d = 0.99;
> x += 0.01;
> d += 0.01;
>
> x -= 1;
> printf ("%8.5f %e\n",floor(x*1e5+0.5)/1e5,floor(x*1e5+0.5)/1e5);
>
> d -= 1;
> printf ("%8.5f %e\n",floor(d*1e5+0.5)/1e5,floor(d*1e5+0.5)/1e5);
>
> return 0;
> }
No argument with any of the above. I notice neither post mentioned
whether the floats were binary or decimal. I wonder how the above might
change if run with compiler and hardware that supported decimal floats?
(Don't want to change the point, as I think it is basically a crime or
at least irresponsible bordering on the criminal for engineers to design
the machines consumers use with such a lack of decimal precision. I
think hardware engineers generally live in a higher ivory tower than
even the OO software people.)
IBM would be doing a public service to put Cowlishaw's decimal code in
the public domain. Don't understand why they don't.
Of course, if we eliminated programmers, then the users would be
responsible for the above results, just as they are when they make a
spreadsheet and there might be less shuddering!
p
p
p
Received on Wed Mar 28 2007 - 17:19:55 CDT