Square root function help!

Pages: 12
Ah
Okay I see what you mean IdeasMan. I revised the code.. Would this be better practice

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

int roundUporDown(double x, double y){


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

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

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

        break;

    }


}
Last edited on
No, read this part again.

TheIdeasMan wrote:
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.


You still have doubles on line 5.

There are lots of ways of doing this, look at these:

http://en.wikipedia.org/wiki/Methods_of_computing_square_roots


The easiest one seems to be the exponential identity. And also the Taylor's series.
or maybe put the characteristics and mantissa's( to maybe the 5th decimal point) into two ints and use those in the loop
@giblit

I don't see any sense in what you are saying. What do you mean by characteristics? What is wrong with (StartVal - StopVal) / StepVal as an int?
It's probably not the best solution but I believe it works try it out yourself.
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <vector>
#include <sstream>

const unsigned short getCharacteristic( const double input )
{
    unsigned short characteristic = 0;
    std::stringstream ss;
    ss << input;
    std::string::iterator it = ss.str().begin();
    while( *it != '.' )
    {
        ss >> characteristic;
        it++;
    }
    return( characteristic );
}

const unsigned short getMantissa( const double input )
{
    unsigned short mantissa = 0 , positionOfDecimal = 0;
    std::stringstream ss;
    std::string temp1 = std::string() , temp2 = std::string();
    std::string::iterator it;
    ss << input;
    ss >> temp1;
    for( it = temp1.begin(); it != temp1.end(); it++ )
    {
        if( *it != '.' )
        {
            positionOfDecimal++;
        } else {
            break;
        }
    }

    for( unsigned int i = positionOfDecimal + 1; i < temp1.size(); i++ )
    {
        temp2 += temp1[i];
    }
    ss.clear();
    ss << temp2;
    ss >> mantissa;

    return( mantissa );
}

int main()
{
    std::vector<double> input( 2 , 0 );
    std::vector<unsigned short> characteristic( 2 , 0 ) , mantissa( 2 , 0 );
    unsigned short characteristicCase( 0 ); //set it to 0 which I will use by default as equal

    std::cout << "Please enter double number 1 to compare.\n> " << std::flush;
    std::cin >> input[ 0 ];
    std::cout << "Please enter double number 2 to compare.\n> " << std::flush;
    std::cin >> input[ 1 ];

    characteristic[ 0 ] = getCharacteristic( input[ 0 ] );
    characteristic[ 1 ] = getCharacteristic( input[ 1 ] );
    mantissa[ 0 ] = getMantissa( input[ 0 ] );
    mantissa[ 1 ] = getMantissa( input[ 1 ] );


    if( characteristic[ 0 ] > characteristic[ 1 ] )
    {
        std::cout << "Input 1 is larger than input 2." << std::endl;
    } else if( characteristic[ 0 ] < characteristic[ 1 ] )
    {
        std::cout << "Input 2 is larger than input 1." << std::endl;
    } else if( characteristic[ 0 ] == characteristic[ 1 ] && mantissa[ 0 ] > mantissa[ 1 ] )
    {
        std::cout << "Input 1 is larger than input 2." << std::endl;
    } else if( characteristic[ 0 ] == characteristic[ 1 ] && mantissa[ 0 ] < mantissa[ 1 ] )
    {
        std::cout << "Input 2 is larger than input 1." << std::endl;
    } else if( characteristic[ 0 ] == characteristic[ 1 ] && mantissa[ 0 ] == mantissa[ 1 ] )
    {
        std::cout << "Input 1 and input 2 are equal." << std::endl;
    }

    return 0;
}
Last edited on
Oh sorry Ideasman, I think i know what you mean now. just revised. I no longer have an ending condition as a loop nor the increment condition so I hope its okay now. And Ill also continue to read through the wikipedia page, anyways here it is.

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, double y){

while(true){
        if((x*x) < (y-0.001)){
            x = x + 0.001;
            continue;
        }

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




}

}


although Ill have to work out converting them to ints
Last edited on
@giblit

Jumping Juniper Berries - Batman!! 83 LOC to compare 2 doubles.You are doing way too much hard work. I really think you need to get out of this habit of looking at things char by char when there are either built in functions or easier methods. See below.

For one, consider that +1.023e-10 is a valid double, as is -1.023E+10 or 1.023E10 or -1.023.

More importantly consider that all we want to do is this: @Irishfitz why couldn't you figure this out yourself? It pretty simple really.

1
2
3
4
5
6
7
8
double begin = 1.0;
double end = 9.0;
double step = 0.1;
int NumberOfTimesToLoop = static_cast<int>( (end - begin)/step ); //should be 80 for this example

for (int a = 0;a < NumberOfTimesToLoop ;++a) {
  // your code
}


To compare using a particular precision, do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const double PRECISION = 0.01;

double a = 2.02;
double b = 2.0;

if( (a-b) > PRECISION  ) {
   std::cout << "a is greater than b within precision\n";
}
else if ( (a-b) < -PRECISION ) {
     std::cout << "a is less than b within precision\n";
}
else {
    std::cout << "a is equal to b within precision\n";
}


You probably should make these functions that return bool. For the equality one, compare the absolute value of the difference to the PRECISION.

@Irishfitz

Also, try to learn about the += -= *= /= operators.
Last edited on
I think the problem lies not in the code, but in the means of which you are computing the square root in the first place. For one, it will take forever to do so- plug in 612, and you'll be waiting all day. My recommendation is Newton's Method, which can be applied to square roots with this simple formula:

nth root of A:

xk+1=(1/n)((n-1)xk+(A/xkn-1))

Here, n is whatever root you are taking it to (in this case, 2). A is what you are finding the root of, and xk is the value calculated before the one you're calculating now, where x0 is your initial guess (it could just be the number divided by 2).

So, how is this more efficient? Well, say if we wanted the square root of 12. Now, we know that this reduces down to 2 times the square root of 3, which rounds to be about... 3.4641 or so. Now, using your algorithm, this would take... a lot of iterations to reach, clearly. However, using the one I just mentioned, with a guess of... 6

x1=(1/2)(6+(12/6)) = 4
x2=(1/2)(4+(12/4)) = 3.5
x3=(1/2)(3.5+(12/3.5)) = 3.464

It has gotten within 3 decimal points by the third iteration. This, compared to your method, which would take (assuming an increment of .001) 3464 increments. That, and yours comes with the issue of floating-point rounding, while this method does not. Essentially, you are going through a lot more difficult of a method than you have to just to calculate a square root. There's no need to increment some billion number of times. Just use the method I provided, and you'll have a sufficient answer within 10 iterations, versus 10000.

As for the guess, just take the input and divide it by 2. It'll be close for smaller values, and if you're doing enough iterations, the difference will be negligible.
Last edited on
Ispil wrote:
My recommendation is Newton's Method

I already provided an example which uses Newton's method earlier in the thread: http://www.cplusplus.com/forum/beginner/102016/#msg548338
@ MiiNiPaa
Can you explain, because I disagree.

You might find it strange, but 0.1+0.1 != 0.2.
Doubles are not precise 4 != 4
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <iomanip>

int main()
{
    double d = 0.1;
    d = d + 0.1;
    std::cout << std::setprecision(25) << d;
}
0.2000000000000000111022302
and another one:
1
2
3
4
5
6
7
8
9
#include <iostream>
int main()
{
    double d = 0.0, x = 1.0;
    for (int i =0; i < 10; ++i)
        d += 0.1;
    if (d != x)
        std::cout << "ouch";
}
ouch

Last edited on
Topic archived. No new replies allowed.
Pages: 12