I am trying to create a function to find the square root of a number. For debugging purposes, it has instructions to print current variable values. The function squareRoot accepts two arguments, x and t. It then declares and initializes n and s. n is the amount to add or subtract, halving every time it is used. s is what is thought to be the current square root. When running, I can clearly see that n is adjusting correctly. However, s stops changing when the first four digits are correct. I am using this call in main():
cout << squareRoot(1000, 10) << "\n";
This should print the square root of 1000 to the nearest tenth, but two weird things happen:
- It doesn't stop at 31.6.
- It stops at 4 digits!
My theory as to why it stops at four digits is this: In multiplying, s loses some of its precision. Is this true? If so, can you tell me how to correct it? If not, what is causing this and how can I correct that?
I tried to solve it already by using another variable, s1, which would be multiplied and checked. Then s would be incremented by n, and s1 synchronized with s. This didn't work, so I went back to the original code.
My code is as follows:
#include <iostream>
using namespace std;
double squareRoot(double x, int t) {
    double s = 0;
    double n = 0.1;
    while ((s*s) <= x) {
         开发者_如何学运维   s += n;
            n *= 2;
            cout << n << "\n" << s << "\n";
    }
    cout << "\n";
    s -= n;
    // Keep changing until margin of error is reached
    while ((((s*s) - x) < (1/t)) || ((x - (s*s) < (1/t)))) {
        // If too high, lower s
        if ((s*s) <= x) {
            s += n;
            n /= 2;
            cout << "Adding 1/2 of previous n\n";
        }
        // If too low, raise s
        else if ((s*s) >= x) {
            s -= n;
            n /= 2;
            cout << "Subtracting 1/2 of previous n\n";
        }
        cout << s << "\n" << n << "\n\n";
    }
    return s;
}
I am running Windows 7 64 bit, MSVC++ 2008 Express. Thank you in advance for all answers!
It converges to the correct square root, but cout only prints six significant digits by default: 31.xxxx.
Also notice that your termination check does not work because (1/t) will always evaluate to 0 for t>1. Use 1./t instead.
Unrelated, but your sqrt algorithm can be sped up by using an existing one, such as Newton's Method.
It goes like this:
double mySqrt(double x, unsigned long accuracy = 10)
{
   if(x < 0.0)
      return(-1.0);
   double retval = 1.0;
   for(unsigned long rep = 0; rep < accuracy; rep++)
      retval = ((x / retval) + retval) / 2.0;
   return(retval);
}
Newton's method also works for cube roots, etc. For decimal exponents, look up the Binomial Theorem.
The reason loop isn't stopping is that loop condition isn't correct. You have
while ((current - target < precision) || (target - current < precision)) {
    ...
}
But either value current - target or value target - current will be <= 0. And 0 < precision. Thus you have equivalent of while (true) {...} loop.
You need something like
while (abs(current - target) > precision) {
    ...
}
(don't know exact function for getting absolute value in C++)
edit
Just noticed, hamster3null wrote about 1/t before me.
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论