Square root function help!

Pages: 12
Im trying to make a square root function that increments the double variable i by 0.1 every loop, however its not working. here's the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
int m;
double i = 0;


 cout << "Enter a number to find its square root: "; cin >> m;


while(i <= m) {

    if((i*i) == m){
        cout << "Square root = " << i << endl;
        break;
    }
    if((i*i) != m){
        i += 0.1;
        continue;
    }

}



the problem is when I change the increment to say just i = i + 1; it prints the message. but when its i += 0.1; it doesnt print the message ever... (ive tried everything i can think of to fix this) any help is appreciated thank you.
You might find it strange, but 0.1+0.1 != 0.2. This is floatig point precision problem. Basically you should not compare floats using ==. And in your case you should use some epsilon so you can guarantee that if i2 < m < (i+1)2, one of the checks will fire and you won't skip nearest value accidentaly
Last edited on
epsilon huh? sounds advanced. However when I do a loop that prints numbers 1 to say 5, and I increment it by 0.1 it'll add together just fine. why does it work for that and not for this case?
Last edited on
Irish what he is saying is that floating/double point numbers are not exact 4 could really be 3.999999999999999999 or even 4.0000000000000000001
try this
1
2
3
4
5
6
7
#include <iostream>
#include <iomanip>
int main( int argc , char** argv )
{
    double a = 4;
    std::cout << std::setprecision( 20 ) << a << std::endl;
}


and more than likely it will output one of those two options mentioned earlier
so when you try and say if 2 * 2 == a it will always come up as false because 4 != 3.9999999999999999999 && 4 != 4.0000000000000000001 ( depending on the compiler )
Last edited on
That's because floating point fractions are imprecise, and do not like comparison with "=="
http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/
See for yourself, where the computer is lost:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <iomanip>      // std::setprecision
using namespace std;

int main(){
	int m;
	double i = 0;
	int PRECISION ; // How many digits you wish to see?
	cout << "Enter a number to find its square root: "; cin >> m;
	cout << "How many digits you wish to see? : "; cin >> PRECISION;
	cout << m << endl;
	while(i <= m) {
		// Uncomment if You settle for some approximation
		//if((i*i) > m - 0.00001 && (i*i) < m + 0.00001){
		if((i*i) == m ){ // Your version
			cout << "Square root = " << i << endl;
			break;
		}
		if((i*i) != m){
			i += 0.1;
			cout << "Trying " << std::setprecision(PRECISION)
				<< i << " * " << i << ": " << i*i << endl;
			continue;
		}
	}
	while(1);
}
Last edited on
giblit: thank you man that makes sense. So does setprecision basically round it down or up (depending on compiler)?

jockx: Thank you, however why did you place a while(1); at the bottom of main? is that significant or no?
It's significant for me, because my Visual C++ Studio closes the console window, and while(1) does not require including any libraries just to hold the window open :D.
Oh! I never thought of that as a replacement for system("PAUSE") lol.
set precision is just an i/o manipulation it display a more precise number you can do setprecision 10000 if you really want and it probably would fill the console up with random numbers to show you how not so precise doubles/floats are.
there is some cases where
1
2
3
4
//double x;
double y = sin(x);
if(y != sin(x))
    std::cout << "WTF?";
Will give you a message.
http://ideone.com/wkVaae

Visual C++ Studio closes the console window
There is options to make it stay. Try to compile in debug configuration. Alternatively run it manually from cmd prompt, place cin >> something, do something but do not place infinite loop in your program.
Last edited on
or go to the second sticky on this forum =p
Keeping the window open with while(1); may be alright during testing, but I wouldn't recommend it in any serious code as it is CPU-hungry. It keeps the processor busy going round that infinite loop.

Meanwhile, here's one of my versions of a square root function. I had intended to compare the new estimate with the previous estimate and exit when they were the same. However in some cases the value can oscillate between two alternating values, so I stored the last two estimates.

All the real work is done on line 10:
newestimate = ((n/estimate) + estimate) * 0.5;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
double SqRoot(double n)
{
    double estimate = n;
    double newestimate = n;
    double prevest;

    do {
        prevest = estimate;
        estimate = newestimate;
        newestimate = ((n/estimate) + estimate) * 0.5;
    } while (newestimate != estimate && newestimate != prevest);

    return estimate;
}
I just made a function that works with square root of hopefully any number now
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

int roundUporDown(double x, int y){


    for(x; x < y; x = x + 0.1){

         if((x*x) < (y-1)){
            continue;
        }

        if((x*x) > (y-1) || (x*x) < (y+1)){
            cout << "Square root = " << x << endl;
            break;
        }

    }


}



so I basically took into account what you guys said about floating point not being precise so I made it so if it was within 1 below or 1 above the user inputed number it would work. Thanks for the help guys really really appreciate it.
Nope. Same problem.

Floating Point (FP) numbers floats & doubles are imprecise because they are binary fractions.

If you want to use FP numbers in a loop don't do it in the end condition or increment expression. Find a way to use ints & convert them to double inside the loop. For example you can work out what (y-x) / 0.1 is as an int.

HTH
TheIdeasMan: Here try it yourself, I just revised it to give you the closest possible answer.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#include <iostream>

using namespace std;

int roundUporDown(double x, double y);

int main()
{
double m;
double i = 0.1;




 cout << "Enter a number to find its square root: "; cin >> m;

roundUporDown(i, m);



}


int roundUporDown(double x, double y){


    for(x; x < y; x = x + 0.01){

         if((x*x) < (y-0.01)){
            continue;
        }

        if((x*x) > (y-0.01) || (x*x) < (y+0.01)){
            cout << "Square root = " << x << endl;
            break;
        }

    }


}
well now you have two doubles so might be even worse. And the problem with doubles most of the time is about the 15th decimal place I believe and for floats probably the 7th place.
btw instead of var = var + VALUE you can do var += VALUE they mean same thing but save some typing
Last edited on
And the problem with doubles most of the time is about the 15th decimal place I believe and for floats probably the 7th place



is there a long double data type? or is that non existent?
@Irishfitz

It may work - (I didn't try it), but I am trying to say that what you are doing is bad practice.

I would be happier if you used a while loop with line 34 as the end condition, and the incrementing of the double number inside the loop.

The first while loop you had was no good because of the equality operators, but now you have improved that a lot with relational operators, but have double in the for loop.
There is long double that just means it is a larger bit not decimal place
Long double gives about two more decimal digits of precision than double.
Pages: 12