web-dev-qa-db-ja.com

sqrt関数を使用せずに平方根を見つけますか?

私は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の値を返します。これに対する解決策を教えてください。

16
Arun Pandey

より良いアルゴリズムがあり、倍精度の最大精度に収束するには最大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から始まります。次に、各ステップで、現在の値yと_x/y_の間の平均を取ることにより、次の近似を改善します。 y = sqrt(x)の場合、同じになります。 y> sqrt(x)の場合、ほぼ同じ量の_x/y_ <sqrt(x)。つまり、非常に高速に収束します。

[〜#〜] update [〜#〜]:非常に大きいまたは非常に小さい数の収束を高速化するために、sqrt()関数を変更してバイナリ指数を抽出し、数値から平方根を計算しました。 _[1, 4)_の範囲。現在、バイナリ指数を取得するには_<math.h>_からfrexp()が必要ですが、frexp()を使用せずにIEEE-754数値形式からビットを抽出することでこの指数を取得できます。

33
mvp

平方根を見つけるために Babylonian method を使用してみてください。

ここに私のコードがあります:

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

がんばろう!

6
Newskooler

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;
 }
2
Zac Howland

sqrt()を使用せずに平方根を見つける必要がある場合は、root=pow(x,0.5)を使用します。

Xは、平方根を見つける必要がある値です。

1
Mani Kant

私が見つけたように、この質問は古く、多くの答えがありますが、私はシンプルでうまく機能する答えを持っています.

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

将来のユーザーの役に立つことを願っています。

1
Himanshu

これは非常に単純な再帰的アプローチです。

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);
}
0
Cameron Monks
//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;
}
0
Kartik

これは非常にシンプルですが、nsafe数値の平方根を見つけるためのアプローチです。基数または指数が自然数であることを知っている自然数のみで機能するため、安全ではありません。 #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;
}
0
PatrickSteiner