1

I have been playing around with the Babylonian square root algorithm from an assignment in my intro to programming class. The program works fine and gives pretty accurate answers. My question stems from something weird happening in the line (while guess != result ) I wrote that while statement to check the two terms, and as soon as they are identical, break the loop. However, if you input, say 50 as the starting number, the loop checks two identical numbers three times before it breaks out, instead of once. Is this because there are more numbers being crunched in the background, that the double data type can't display? I know double can go up to 15 decimal places. I hope i'm wording this in a way that is understandable, if anyone needs clarification just ask. PS- if anyone has tips to help make my code cleaner, please do let me know, I'm trying to learn how to format my code to be as readable as possible.

#include <iostream>

using namespace std;

int main()
{
    double input,       // Users number
           guess = 2,   // First guess, always 2 at beginning
           result,      // altered guess, becomes guess 1 when repeated
           r;           // input divided by guess

    int steps = 1,      // keeps track of step number, for debugging
        loop = 1;       // controls continue loop

    string error_1 = " Warning: input is negative, please pick a new one";

    while (loop == 1)
    {
        cout << "--Babylonian Square Root Algorithm--" << endl;
        cout << "Type a positive number to find its square root: ";
        cin >> input;

        if (input >= 0)
        {
            while (guess != result) // test here for within 1%
            {
                r = input / guess;
                result = (guess + r) / 2;
                // DEBUG
                cout << "-------" << endl;
                cout << " Step # " << steps << endl;
                cout << "-------" << endl;
                cout << " R) " << r << endl;
                cout << " Guess) " << guess << endl;
                cout << " Result) " << result << endl;
                steps++;

                guess = result;
                result = (guess + r) / 2;
                cout << result << " is the approximate square root of " << input << endl;
                //DEBUG
                cout << " Steps required: " << steps - 1 << endl;
            }
            else
            {
                cout << error_1 << endl;
            }
            cout << "Continue?  (Yes = 1, No = 0)" << endl;
            guess = 2;
            result = 0;
            steps = 1;
            cin >> loop;
            cout << "------------------------------------------------------" << endl;
        }
        return 0;
    }
}
sokkyoku
  • 2,161
  • 1
  • 20
  • 22
Taharix
  • 13
  • 4
  • 1
    The first problem is that you use `result` before it is initialized. That is *undefined behavior*. The other problem is the one linked to in the comment by @NathanOliver. – Some programmer dude Sep 29 '16 at 13:12
  • @ Jaochim Pileborg I think I initialized result where my double variables are, didn't I? – Taharix Sep 29 '16 at 13:14
  • Also, thanks for the link, I did not know how to word this to seach for a possible duplicate – Taharix Sep 29 '16 at 13:15
  • Wait, I see what you mean, would setting result to zero when declared fix this issue? I understand what you mean now, my apologies – Taharix Sep 29 '16 at 13:17
  • It still repeats the behavior, but ill read through the link provided to learn how floats work, thanks so much for your time. – Taharix Sep 29 '16 at 13:19
  • Consistent and clear indentation would be a big help! – Lightness Races in Orbit Sep 29 '16 at 14:08
  • 1
    _"I think I initialized result where my double variables are, didn't I?"_ Nope! You need `= 0` if you want it to start life at 0. – Lightness Races in Orbit Sep 29 '16 at 14:08
  • 1
    In C++ local stack variables are not initialized by default. Any modern C++ compiler does usually emit warning for a possible uninitialized variable usage, switch warnings ON (-Wall for gcc) and try to keep the source warning-less. – Ped7g Sep 29 '16 at 14:38
  • About the accepted answer: it's missing the most important part. Don't do `double/float == exact_number` (unless you know exactly what you are doing and why that absolute exactness may be reached). HW floating point numbers should be compared with some error_margin allowed (for equality). The error_margin should be designed according to the way your formulas calculate with values, so the margin covers the worst possible cumulative inaccuracy. – Ped7g Sep 29 '16 at 14:45
  • @Ped7g Thanks for the info, i'm pretty new so I don't exactly know how to implement a check for a margin of error yet, but i'll look into it. – Taharix Sep 29 '16 at 14:53
  • `if (abs(exact_number - value_to_compare) <= error_margin) { /* ... value is almost equal ... */ }` – Ped7g Sep 29 '16 at 14:59

1 Answers1

2

"guess" and "result" are "double" type, it has higher precision than you can see with default cout floating point digit display length.

you think that the numbers are same, but they are not. farther you go from decimal point you can see the difference.

Solution 1: change the cout decimal number display range to a longer value, so that you can see that the numbers are actually different, so while loop didn't break. use cout.precision(17); at the start of code.

Solution 2: change the datatype of guess & result to "float"

kernelman
  • 992
  • 1
  • 13
  • 28
  • 1
    Thank you, you made the reason and possible solutions very clear – Taharix Sep 29 '16 at 14:44
  • changing the doubles to floats actually fixed another issue where the sqrt of zero was taking over 1000 steps to complete, now it only takes 150 ish, due to better rounding I assume. Thanks! – Taharix Sep 29 '16 at 15:03
  • @Taharix It's not really "better rounding", it's because `float` has less precision than `double`, so it takes far fewer iterations before the result is indistinguishable from zero. – TripeHound Sep 29 '16 at 15:25