繁体   English   中英

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

[英]Finding square root without using sqrt function?

我正在寻找无需使用sqrt函数即可找出平方根的算法,然后尝试进行编程。 我最终在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;
     } 

现在的问题是初始化声明中的迭代次数nCount(这里是50)。 例如,找出36的平方根需要22次迭代,所以没有问题,而找到15625的平方根需要50次以上迭代,因此它将在50次迭代后返回temp的值。 请为此提供解决方案。

有一个更好的算法,最多需要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)
}

算法以1作为平方根值的第一近似值开始。 然后,在每个步骤上,通过取当前值yx/y之间的平均值来改善下一个近似。 如果y = sqrt(x) ,则将相同。 如果y > sqrt(x) ,则x/y < sqrt(x)大约相等。 换句话说,它将很快收敛。

更新 :为加快非常大或非常小的数字的收敛,更改了sqrt()函数以提取二进制指数并从[1, 4)范围内的数字计算平方根。 现在它需要来自<math.h> frexp()来获取二进制指数,但是可以通过从IEEE-754数字格式中提取位而不使用frexp()来获得该指数。

为什么不尝试使用巴比伦方法来找到平方根。

这是我的代码:

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;
}

祝好运!

完全删除您的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;
 }

如果需要在不使用sqrt()情况下找到平方根,请使用root=pow(x,0.5)

其中x是您需要查找其平方根的值。

当我发现这个问题很旧并且有很多答案时,但我有一个简单而有效的答案。

#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;
}

希望对将来的用户有所帮助。

//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;
}

这是一种非常简单但不安全的方法来找到数字的平方根。 不安全,因为它仅适用于自然数,您知道底数和指数均为自然数。 我必须将其用于既不允许使用#include <cmath> -library的任务,也不允许使用指针的任务。

效能=基本^指数

// 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;
}

这是一种非常简单的递归方法。

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);
}

这是一个非常出色的代码,可以找到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;
}

在查看了之前的答复之后,我希望这将有助于解决任何歧义。 如果先前的解决方案与我的解决方案之间的相似性是虚假的,或者不清楚这种求解根的方法,那么我也制作了一个可以在此处找到的图。

这是一个工作根函数,能够解决任何nth根问题

出于这个问题,默认值是平方根

#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)))));
}

说明

点击这里查看图表

这通过泰勒级数,对数性质和一点代数起作用。

举个例子:

log A = N
   x

*注 :对于平方根,N = 2; 对于任何其他根,您只需更改一个变量N。

1)更改基准,将基准“ x”对数函数转换为自然对数,

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

2)重新排列以隔离ln(x),最后只是'x',

ln(A)/N = ln(x)

3)将双方都设为'e'的指数,

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

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] + . . .

*注意 :继续进行该系列以提高准确性。 为简便起见,在我的函数中使用10 ^ 9表示自然对数的级数收敛,该数约为7位,即百万分之一,为了精确起见,

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

5)现在,只需将此自然对数方程式插入到步骤3中获得的简化方程式中即可。

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

6)这种实现似乎有点过头了; 但是,其目的是演示无需猜测和检查即可解决根源的方法。 此外,它还使您能够用自己的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