簡體   English   中英

平方根算法 C++

[英]square root algorithm C++

如果輸入的數字超過 12 位,我無法弄清楚為什么這個算法會進入無限循環。 誰能明白為什么它永遠不會結束? 謝謝。 我剛剛更新了算法以使用 fabs() 函數並且仍然得到無限循環。

double squareroot(double x)

{ /* computes the square root of x */

/* make sure x is not negative .. no math crimes allowed! */
assert( x >= 0 );
if (x==0) return 0;

/* the sqrt must be between xhi and xlo */
double xhi = x;
double xlo = 0;
double guess = x/2;

/* We stop when guess*guess-x is very small */

while (abs(guess*guess-x) > 0.00001 )
{
    if (guess*guess > x){
        xhi = guess;
    }

    else {
        xlo = guess;
    }

    guess = (xhi + xlo)/2;
}
return guess;
}

我相信您應該在終止時使用相對誤差,而不是絕對誤差。

while (abs((guess*guess-x) / guess) > 0.00001)

否則將需要很長時間(它不是無限循環)來計算非常長的值的平方根。

http://en.wikipedia.org/wiki/Approximation_error

干杯!

編輯:此外,在評論中指出的下方,這是值得檢查,如果guess是為了避免與一些特定的角落情況下,無限循環已經猜到了。

我建議等到你有一個穩定的答案,而不是擺弄 epsilon 值:

double squareroot(double x)
{
    if (x < 1) return 1.0 / squareroot(x);  // MSalter's general solution

    double xhi = x;
    double xlo = 0;
    double guess = x/2;

    while (guess * guess != x)
    {
        if (guess * guess > x)
            xhi = guess;
        else
            xlo = guess;

        double new_guess = (xhi + xlo) / 2;
        if (new_guess == guess)
            break; // not getting closer
        guess = new_guess;
    }
    return guess;
}

這不是對您問題的直接回答,而是一種替代解決方案。

您可以使用牛頓法求根

assert(x >= 0);
if (x == 0)
    return 0;

double guess = x;
for (int i=0; i<NUM_OF_ITERATIONS; i++)
    guess -= (guess*guess-x)/(2*guess);
return guess;

24 次迭代應該可以獲得足夠好的近似值,但您也可以檢查絕對差異。

http://floating-point-gui.de/errors/comparison/

嘿,看起來你不應該像那樣使用 abs() 。 在某些情況下它應該停止,但我不會,因為它的精度有限。

而是使用 fabs()

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

我會說,當數字足夠大時,您不能使用絕對 epsilon 值,因為它不符合精度。

嘗試使用相對比較。 考慮以下函數來檢查 2 個雙打是否相等:

bool are_eql(double n1, double n2, double abs_e, double rel_e)
{
  // also add check that n1 and n2 are not NaN
  double diff = abs(n1 - n2);
  if (diff < abs_e)
    return true;
  double largest = max(abs(n1), abs(n2));
  if (diff < largest * rel_e)
    return true;
  return false;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM