Re: Floating Point Approximations.

From: Bob Badour <bbadour_at_pei.sympatico.ca>
Date: Wed, 28 Mar 2007 17:19:31 GMT
Message-ID: <DsxOh.16545$PV3.170662_at_ursa-nb00s0.nbnet.nb.ca>


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;

} Received on Wed Mar 28 2007 - 19:19:31 CEST

Original text of this message