简体   繁体   English

查找平方根而不使用sqrt函数?

[英]Finding square root without using sqrt function?

I was finding out the algorithm for finding out the square root without using sqrt function and then tried to put into programming. 我正在寻找无需使用sqrt函数即可找出平方根的算法,然后尝试进行编程。 I end up with this working code in C++ 我最终在C ++中获得了这个工作代码

    #include <iostream>
    using namespace std;

    double SqrtNumber(double num)
    {
             double lower_bound=0; 
             double upper_bound=num;
             double temp=0;                    /* ek edited this line */

             int nCount = 50;

        while(nCount != 0)
        {
               temp=(lower_bound+upper_bound)/2;
               if(temp*temp==num) 
               {
                       return temp;
               }
               else if(temp*temp > num)

               {
                       upper_bound = temp;
               }
               else
               {
                       lower_bound = temp;
               }
        nCount--;
     }
        return temp;
     }

     int main()
     {
     double num;
     cout<<"Enter the number\n";
     cin>>num;

     if(num < 0)
     {
     cout<<"Error: Negative number!";
     return 0;
     }

     cout<<"Square roots are: +"<<sqrtnum(num) and <<" and -"<<sqrtnum(num);
     return 0;
     } 

Now the problem is initializing the number of iterations nCount in the declaratione ( here it is 50). 现在的问题是初始化声明中的迭代次数nCount(这里是50)。 For example to find out square root of 36 it takes 22 iterations, so no problem whereas finding the square root of 15625 takes more than 50 iterations, So it would return the value of temp after 50 iterations. 例如,找出36的平方根需要22次迭代,所以没有问题,而找到15625的平方根需要50次以上迭代,因此它将在50次迭代后返回temp的值。 Please give a solution for this. 请为此提供解决方案。

There is a better algorithm, which needs at most 6 iterations to converge to maximum precision for double numbers: 有一个更好的算法,最多需要6次迭代才能收敛到双精度的最大精度:

#include <math.h>

double sqrt(double x) {
    if (x <= 0)
        return 0;       // if negative number throw an exception?
    int exp = 0;
    x = frexp(x, &exp); // extract binary exponent from x
    if (exp & 1) {      // we want exponent to be even
        exp--;
        x *= 2;
    }
    double y = (1+x)/2; // first approximation
    double z = 0;
    while (y != z) {    // yes, we CAN compare doubles here!
        z = y;
        y = (y + x/y) / 2;
    }
    return ldexp(y, exp/2); // multiply answer by 2^(exp/2)
}

Algorithm starts with 1 as first approximation for square root value. 算法以1作为平方根值的第一近似值开始。 Then, on each step, it improves next approximation by taking average between current value y and x/y . 然后,在每个步骤上,通过取当前值yx/y之间的平均值来改善下一个近似。 If y = sqrt(x) , it will be the same. 如果y = sqrt(x) ,则将相同。 If y > sqrt(x) , then x/y < sqrt(x) by about the same amount. 如果y > sqrt(x) ,则x/y < sqrt(x)大约相等。 In other words, it will converge very fast. 换句话说,它将很快收敛。

UPDATE : To speed up convergence on very large or very small numbers, changed sqrt() function to extract binary exponent and compute square root from number in [1, 4) range. 更新 :为加快非常大或非常小的数字的收敛,更改了sqrt()函数以提取二进制指数并从[1, 4)范围内的数字计算平方根。 It now needs frexp() from <math.h> to get binary exponent, but it is possible to get this exponent by extracting bits from IEEE-754 number format without using frexp() . 现在它需要来自<math.h> frexp()来获取二进制指数,但是可以通过从IEEE-754数字格式中提取位而不使用frexp()来获得该指数。

Why not try to use the Babylonian method for finding a square root. 为什么不尝试使用巴比伦方法来找到平方根。

Here is my code for it: 这是我的代码:

double sqrt(double number)
{
    double error = 0.00001; //define the precision of your result
    double s = number;

    while ((s - number / s) > error) //loop until precision satisfied 
    {
        s = (s + number / s) / 2;
    }
    return s;
}

Good luck! 祝好运!

Remove your nCount altogether (as there are some roots that this algorithm will take many iterations for). 完全删除您的nCount (因为此算法需要很多迭代才能找到一些根)。

double SqrtNumber(double num)
{
    double lower_bound=0; 
    double upper_bound=num;
    double temp=0;

    while(fabs(num - (temp * temp)) > SOME_SMALL_VALUE)
    {
           temp = (lower_bound+upper_bound)/2;
           if (temp*temp >= num)
           {
                   upper_bound = temp;
           }
           else
           {
                   lower_bound = temp;
           }
    }
    return temp;
 }

if you need to find square root without using sqrt() ,use root=pow(x,0.5) . 如果需要在不使用sqrt()情况下找到平方根,请使用root=pow(x,0.5)

Where x is value whose square root you need to find. 其中x是您需要查找其平方根的值。

As I found this question is old and have many answers but I have an answer which is simple and working great.. 当我发现这个问题很旧并且有很多答案时,但我有一个简单而有效的答案。

#define EPSILON 0.0000001 // least minimum value for comparison
double SquareRoot(double _val) {
    double low = 0; 
    double high = _val;
    double mid = 0; 

    while (high - low > EPSILON) {
            mid = low + (high - low) / 2; // finding mid value
            if (mid*mid > _val) {
                high = mid;
            } else {
                low = mid;
            }    
    }   
    return mid;
}

I hope it will be helpful for future users. 希望对将来的用户有所帮助。

//long division method.
#include<iostream>
using namespace std;
int main() {
int n, i = 1, divisor, dividend, j = 1, digit;
cin >> n;
while (i * i < n) {
    i = i + 1;
}
i = i - 1;
cout << i << '.';

divisor  = 2 * i;
dividend = n - (i * i );
while( j <= 5) {
    dividend = dividend * 100;
    digit = 0;
    while ((divisor * 10 + digit) * digit < dividend) {
        digit = digit + 1;
    }
    digit = digit  - 1;
    cout << digit;
    dividend = dividend - ((divisor * 10 + digit) * digit);
    divisor = divisor * 10 + 2*digit;
    j = j + 1;
}
cout << endl;
return 0;
}

Here is a very simple but unsafe approach to find the square-root of a number. 这是一种非常简单但不安全的方法来找到数字的平方根。 Unsafe because it only works by natural numbers, where you know that the base respectively the exponent are natural numbers. 不安全,因为它仅适用于自然数,您知道底数和指数均为自然数。 I had to use it for a task where i was neither allowed to use the #include<cmath> -library, nor i was allowed to use pointers. 我必须将其用于既不允许使用#include <cmath> -library的任务,也不允许使用指针的任务。

potency = base ^ exponent 效能=基本^指数

// FUNCTION: square-root
int sqrt(int x)
{
    int quotient = 0;
    int i = 0;

    bool resultfound = false;
    while (resultfound == false) {
        if (i*i == x) {
          quotient = i;
          resultfound = true;
        }
        i++;
    }
    return quotient;
}

This a very simple recursive approach. 这是一种非常简单的递归方法。

double mySqrt(double v, double test) {
    if (abs(test * test - v) < 0.0001) {
        return test;
    }

    double highOrLow = v / test;
    return mySqrt(v, (test + highOrLow) / 2.0);
}
double mySqrt(double v) {
    return mySqrt(v, v/2.0);
}

Here is a very awesome code to find sqrt and even faster than original sqrt function. 这是一个非常出色的代码,可以找到sqrt,甚至比原始sqrt函数还要快。

float InvSqrt (float x) 
{
    float xhalf = 0.5f*x;
    int i = *(int*)&x;
    i = 0x5f375a86 - (i>>1);
    x = *(float*)&i;
    x = x*(1.5f - xhalf*x*x);
    x = x*(1.5f - xhalf*x*x);
    x = x*(1.5f - xhalf*x*x);
    x=1/x;
    return x;
}

After looking at the previous responses, I hope this will help resolve any ambiguities. 在查看了之前的答复之后,我希望这将有助于解决任何歧义。 In case the similarities in the previous solutions and my solution are illusive, or this method of solving for roots is unclear, I've also made a graph which can be found here . 如果先前的解决方案与我的解决方案之间的相似性是虚假的,或者不清楚这种求解根的方法,那么我也制作了一个可以在此处找到的图。

This is a working root function capable of solving for any nth-root 这是一个工作根函数,能够解决任何nth根问题

( default is square root for the sake of this question ) 出于这个问题,默认值是平方根

#include <cmath> 
// for "pow" function

double sqrt(double A, double root = 2) {
    const double e = 2.71828182846;
    return pow(e,(pow(10.0,9.0)/root)*(1.0-(pow(A,-pow(10.0,-9.0)))));
}

Explanation : 说明

click here for graph 点击这里查看图表

This works via Taylor series, logarithmic properties, and a bit of algebra. 这通过泰勒级数,对数性质和一点代数起作用。

Take, for example: 举个例子:

log A = N
   x

*Note : for square-root, N = 2; *注 :对于平方根,N = 2; for any other root you only need to change the one variable, N. 对于任何其他根,您只需更改一个变量N。

1) Change the base, convert the base 'x' log function to natural log, 1)更改基准,将基准“ x”对数函数转换为自然对数,

log A   =>   ln(A)/ln(x) = N
   x

2) Rearrange to isolate ln(x), and eventually just 'x', 2)重新排列以隔离ln(x),最后只是'x',

ln(A)/N = ln(x)

3) Set both sides as exponents of 'e', 3)将双方都设为'e'的指数,

e^(ln(A)/N) = e^(ln(x))  >~{ e^ln(x) == x }~>  e^(ln(A)/N) = x

4) Taylor series represents "ln" as an infinite series, 4)泰勒级数表示“ ln”为无穷级数,

ln(x) = (k=1)Sigma: (1/k)(-1^(k+1))(k-1)^n

           <~~~ expanded ~~~>

[(x-1)] - [(1/2)(x-1)^2] + [(1/3)(x-1)^3] - [(1/4)(x-1)^4] + . . .

*Note : Continue the series for increased accuracy. *注意 :继续进行该系列以提高准确性。 For brevity, 10^9 is used in my function which expresses the series convergence for the natural log with about 7 digits, or the 10-millionths place, for precision, 为简便起见,在我的函数中使用10 ^ 9表示自然对数的级数收敛,该数约为7位,即百万分之一,为了精确起见,

ln(x) = 10^9(1-x^(-10^(-9)))

5) Now, just plug in this equation for natural log into the simplified equation obtained in step 3. 5)现在,只需将此自然对数方程式插入到步骤3中获得的简化方程式中即可。

e^[((10^9)/N)(1-A^(-10^-9)] = nth-root of (A)

6) This implementation might seem like overkill; 6)这种实现似乎有点过头了; however, its purpose is to demonstrate how you can solve for roots without having to guess and check. 但是,其目的是演示无需猜测和检查即可解决根源的方法。 Also, it would enable you to replace the pow function from the cmath library with your own pow function: 此外,它还使您能够用自己的pow函数替换cmath库中的pow函数:

double power(double base, double exponent) {
    if (exponent == 0) return 1;
    int wholeInt = (int)exponent;
    double decimal = exponent - (double)wholeInt;
    if (decimal) {
        int powerInv = 1/decimal;
        if (!wholeInt) return root(base,powerInv);
        else return power(root(base,powerInv),wholeInt,true);
    }
    return power(base, exponent, true);
}

double power(double base, int exponent, bool flag) {
    if (exponent < 0) return 1/power(base,-exponent,true);
    if (exponent > 0) return base * power(base,exponent-1,true);
    else return 1;
}

int root(int A, int root) {
    return power(E,(1000000000000/root)*(1-(power(A,-0.000000000001))));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM