1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Help Floating Point Loops With Square Root

Discussion in 'C++' started by ay2306, May 16, 2014.

  1. ay2306

    ay2306 New Member

    Joined:
    May 16, 2014
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    #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
     
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,293
    Likes Received:
    365
    Trophy Points:
    83
    Re: Guys Help me

    Just 10 because you output lot of times in loop
     
  3. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    Re: Guys Help me

    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 likes this.

Share This Page