Help Floating Point Loops With Square Root

ay2306's Avatar, Join Date: May 2014
Newbie Member
#include<iostream.h>
#include<stdio.h>
#include<conio.h>

void main()
{int a;
float i;
cout << "Enter any number";
cin >> a;
for (i=0,i*i<=a;i+=0.001)
{
clrscr();
cout << "The square root of " << a << " is ";
printf("%.2f",i);
}

}
// The problem is that when i put 100, it gives 9.9 instead of 10
1
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
Your problem is almost certainly down to the inaccuracy of floating point maths. You might also be seeing some compiler-specific behaviour. I'm using Visual Studio 2010.

That said, I get different results depending on the output format I use. I've updated your code:

Code:
void test59()
{
	int a, lineno=0;
	float i;
	cout << "Enter any number";
	cin >> a;
	for (i=0; i*i<=a; i+=0.001)
	{
		float res=i*i;
		cout << lineno++ << " The square root of " << a << " is ";
		printf("%.2f -- %.2f * %.2f = %.2f\n",i,i,i,res);
	}
}
This is what I get using %.2f as the output format:

...
9990 The square root of 100 is 9.99 -- 9.99 * 9.99 = 99.81
9991 The square root of 100 is 9.99 -- 9.99 * 9.99 = 99.83
9992 The square root of 100 is 9.99 -- 9.99 * 9.99 = 99.85
9993 The square root of 100 is 9.99 -- 9.99 * 9.99 = 99.87
9994 The square root of 100 is 9.99 -- 9.99 * 9.99 = 99.89
9995 The square root of 100 is 10.00 -- 10.00 * 10.00 = 99.91
9996 The square root of 100 is 10.00 -- 10.00 * 10.00 = 99.93
9997 The square root of 100 is 10.00 -- 10.00 * 10.00 = 99.95
9998 The square root of 100 is 10.00 -- 10.00 * 10.00 = 99.97
9999 The square root of 100 is 10.00 -- 10.00 * 10.00 = 99.99

Changing the output format to %.4f gives this:

...
9990 The square root of 100 is 9.9904 -- 9.9904 * 9.9904 = 99.8082
9991 The square root of 100 is 9.9914 -- 9.9914 * 9.9914 = 99.8282
9992 The square root of 100 is 9.9924 -- 9.9924 * 9.9924 = 99.8482
9993 The square root of 100 is 9.9934 -- 9.9934 * 9.9934 = 99.8682
9994 The square root of 100 is 9.9944 -- 9.9944 * 9.9944 = 99.8882
9995 The square root of 100 is 9.9954 -- 9.9954 * 9.9954 = 99.9082
9996 The square root of 100 is 9.9964 -- 9.9964 * 9.9964 = 99.9282
9997 The square root of 100 is 9.9974 -- 9.9974 * 9.9974 = 99.9482
9998 The square root of 100 is 9.9984 -- 9.9984 * 9.9984 = 99.9682
9999 The square root of 100 is 9.9994 -- 9.9994 * 9.9994 = 99.9882

So here you can already see some inaccuracy creeping in. You're starting with 0 and adding 0.001 each time. So what's with this 4 digit? Why is it 9.9994 in line 9999 instead of 9.9990?

Well this is down to floating point inaccuracy, which enters when numbers are converted between decimal and binary.

Let me give you a decimal example you're probably familiar with. What's the decimal expansion of the fraction 1/3?

It's 0.(3), i.e. zero, point, followed by an infinite number of threes.
But computers can't store numbers using an infinite amount of space. So: what's the decimal expansion of 1/3 using no more than 4 decimal places?

It's 0.3333. And that's the problem. Any maths you now do with 0.3333 will not be equivalent to paper maths with 1/3. Multiply it by 3 and you should get 1.0000. But you don't - you get 0.9999.
Now in maths 0.(9)=1, so there is no problem there. But the computer is stuck with a finite number of places.

It gets worse with other fractions. 5/9 in 4 places is 0.5555. Arguably we should round this up. That gives us 0.5556. 5/9 squared=25/81=0.30864198 (rounding the Windows Calculator result off at 8dp). But 0.5556 squared=0.30869136 which is incorrect in the 5th place. Worse: multiply this by 81 which of course should give 25, but we actually get 25.00400016.

Try converting 0.1 to binary. In a spreadsheet (I'm using OpenOffice Calc) set A1=16, B1=15, C1 to the formula "=IF(B1>=A1;1;0)".
Now set A2 to the formula "=A1/2", B2 to the formula "=B1-A1*C1" and copy C1 to C2.
Now copy and paste A2-C2 to A3-C40.

A1 is the value of the binary place (binary equivalent of decimal place); B1 is the value we want to convert, and the C column is the binary expansion of that value.
The example I've started with, 15, is easy; it's just 01111.(0). No problem there.
Now set B1 to 0.1. All being well your C column should now translate to 00000.000(1100). And there's the inaccuracy. Decimal 0.1 doesn't have an exact representation in a finite number of bits.
And if I extend the sheet until B becomes zero (at B60) then I get 12 groups of 1100, then a 1101, so even OpenOffice becomes inaccurate at this point.
shabbir like this
0
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Just 10 because you output lot of times in loop