平方根算法C ++

时间:2015-01-15 06:53:14

标签: c++ algorithm oop square-root

如果输入的数字超过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;
}

5 个答案:

答案 0 :(得分:5)

我相信你应该使用相对错误来终止,而不是绝对错误。

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

否则,计算很长值的平方根需要很长时间(它不是无限循环)。

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

干杯!

编辑:此外,正如评论中所述,值得检查guess是否已经猜到,以避免出现一些特定极端情况的无限循环。

答案 1 :(得分:3)

我建议等到你得到一个稳定的答案,而不是摆弄epsilon值:

double squareroot(double x)
{
    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;
}

答案 2 :(得分:2)

这不是您问题的直接答案,而是替代解决方案。

您可以使用Newton's method for finding roots

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次迭代可以让你得到足够好的近似值,但你也可以检查绝对差值。

答案 3 :(得分:0)

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

嘿,看起来你不应该像那样使用abs()。在某些情况下,它应该停止但我不会因为它的精度有限而无法使用。

而是使用fabs()

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

答案 4 :(得分:0)

我说当数字足够大时你不能使用绝对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;
}