Re: Floating Point Approximations.

From: Bob Badour <bbadour_at_pei.sympatico.ca>
Date: Wed, 28 Mar 2007 22:56:58 GMT
Message-ID: <_oCOh.16680$PV3.171440_at_ursa-nb00s0.nbnet.nb.ca>


paul c wrote:

> 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?

The epsilon would be 16 times larger for BCD floats. ie. 5e-7 versus 2^-25 Received on Thu Mar 29 2007 - 00:56:58 CEST

Original text of this message