Re: Floating Point Approximations.
From: paul c <toledobythesea_at_oohay.ac>
Date: Wed, 28 Mar 2007 22:19:55 GMT
Message-ID: <fSBOh.84735$zU1.64713_at_pd7urf1no>
>
>
> 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;
> }
Date: Wed, 28 Mar 2007 22:19:55 GMT
Message-ID: <fSBOh.84735$zU1.64713_at_pd7urf1no>
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?
p
p
p Received on Thu Mar 29 2007 - 00:19:55 CEST