【问题标题】:Getting an infinite loop in Babylonian Algorithm for square roots in C++在巴比伦算法中获取 C++ 平方根的无限循环
【发布时间】:2014-09-22 03:24:59
【问题描述】:

我在整个互联网上彻底搜索了这个主题,线程要么死了,要么使用了与我书中描述的不同的方法。

例如,http://www.geeksforgeeks.org/square-root-of-a-perfect-square/。这对我不起作用,因为我的算法需要循环直到达到最后“猜测”的 1%。

这是文中的问题。

计算数字 n 平方根的巴比伦算法如下:

  1. 猜测数字(您可以选择 n/2 作为初始猜测)。
  2. 计算 r = n / 猜测
  3. 设置guess = (guess + r) / 2
  4. 返回步骤 2 进行尽可能多的迭代。步骤 2 和 3 重复的次数越多,猜测就越接近 n 的平方根。

编写一个程序,为 n 输入一个整数,遍历 巴比伦算法,直到猜测在前一个猜测的 1% 以内, 并将答案输出为双精度数。

我写了以下代码:

#include <iostream>

using std::cout;
using std::cin;
using std::endl;

int main()
{
int  n;
double r, guess(4), lastGuess;

cout << "Enter a number to find the square root of: ";
cin >> n;

do
{

    r = n / guess;
    lastGuess = guess;
    guess = ( guess + r ) / 2;

//  cout <<"Guess: " << guess << endl;
//  cout <<"Last Guess: " << lastGuess << endl;

    cout << "Guess : " << guess  << endl;
    cout << "Last Guess 1% = " << lastGuess + ( lastGuess * 0.01 ) << endl;
    cout << "r = " << r << endl;

} while( guess >= lastGuess * 0.01 );
cout << r;

return 0;
}

程序计算出 r 的正确答案,但循环并未终止,尽管对 lastGuess 的猜测大于 1%。

当输入 144 作为 n 时,该程序产生以下输出。

....
r = 12
Guess : 12
Last Guess 1% = 12.12
r = 12
Guess : 12
Last Guess 1% = 12.12
r = 12
Guess : 12
Last Guess 1% = 12.12
r = 12
Guess : 12
Last Guess 1% = 12.12
....

根 (r) 是正确的 (12)。猜测比 lastGuess (12

【问题讨论】:

    标签: c++ algorithm square-root


    【解决方案1】:

    如果你想增加 1%,你需要乘以 1.01,而不是 0.01。

    while( guess >= lastGuess * 1.01 );
    

    顺便说一句,当猜测增长超过 1% 时,它会迭代。您还应该考虑相反的情况,即它可能缩小了 1% 以上。近似值可以从任一方向接近答案。 (它将从右侧接近正根,从左侧接近负根。)

    【讨论】:

    • 对!这是对的。我原来的表达是 lastGuess +( lastGuess * 0.01 )。我出于一个我不记得的原因把它拿出来了。现在说得通了。这应该与 (lastGuess * 1.01) 相同。当 n 小于 4 时,我现在也明白你的意思了。非常感谢!
    • "你也应该考虑到相反的情况,它可能已经缩小了 1% 以上" 幸运的是,迭代次数交替过高和过低。
    • @DavidEisenstat Newton 的方法可以交替使用。巴比伦方法倾向于从右侧收敛。
    • 实际上,它总是从右侧收敛,所以我关于另一张检查是多余的评论的评论。
    • @DavidEisenstat 从技术上讲,当您考虑负根时,它将从外部收敛。如果你猜 100 的平方根为 -20,它会从左边收敛到 -10。
    【解决方案2】:

    在打印您正在使用的 lastGuess

     lastGuess + ( lastGuess * 0.01 )
    

    但是在检查你正在使用的循环条件时

    lastGuess*0.01
    

    所以在循环条件下使用与打印lastGuess 值相同的公式。

    【讨论】:

      【解决方案3】:

      要正确退出循环,请使用与此类似的内容。

      void f(int N)
      {
          double x = N / 4;
          double prev = 0.0f;
      
          while(1)
          {
              x = 0.5 * (x + N / x);
              if (prev == x)
                  break;
      
              prev = x;
              printf("val: %f\n", x);
          }
      
          printf("SQRT(%d) = %f\n", N, x);
      }
      

      【讨论】:

        【解决方案4】:

        我的书中也有同样的问题。这是我写的,效果很好。

        #include <iostream>
        using namespace std;
        int main()
        {
            double guess, root, previousGuess;
            int number;
            cout << "Enter a number to find the Babylonian square root.\n";
            cin >> number;
            cout << "You want to find the square root of " << number << ".\n";
            cout << "Enter a guess for the square root.\n";
            cin >> guess;
        
            do
            {
                root = number / guess;
                previousGuess = guess;
                guess = (guess + root ) / 2;
        
            } while(guess < 0.99*previousGuess || guess > 1.01*previousGuess);
        
            cout << "The answer is " << guess << ".\n";
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-13
          • 2017-09-25
          相关资源
          最近更新 更多