我不明白这个无限循环

I don't understand this infini-loop

如果这看起来很容易解决,我很抱歉,但我在做本应是简单的 while 循环的事情时遇到了一些奇怪的事情。谁能帮我解决为什么这个循环永远持续下去?

此代码专为这个简单的练习而设计:

There is an old story that the emperor wanted to thank the inventor of the game of chess and asked the inventor to name his reward. The inventor asked for one grain of rice for the first square, 2 for the second, 4 for the third, and so on, doubling for each of the 64 squares. That may sound modest, but there wasn’t that much rice in the empire! Write a program to calculate how many squares are required to give the inventor at least 1000 grains of rice, at least 1,000,000 grains, and at least 1,000,000,000 grains. You’ll need a loop, of course, and probably an int to keep track of which square you are at, an int to keep the number of grains on the current square, and an int to keep track of the grains on all previous squares. We suggest that you write out the value of all your variables for each iteration of the loop so that you can see what’s going on.

这是我的代码:

#include <iostream>

using namespace std;

int main()
{
  double square = 2;
  double rice = 2;
  while (rice < 1000000000, rice *= 2)
  {
    cout << "There is " << rice << " pieces of rice that the inventor owns at square " 
         << square << endl;
    cout << "\n";
    square++;
  }
}

如果这有什么不同,我重写了这段代码以适应 java 并在 eclipse 上得到了同样的结果。

您在 while 表达式中使用了逗号运算符。

不要这样做。

循环中的条件表达式应该始终简单易读,并且应该没有副作用。正如您的问题所示,逗号运算符消除了这种简单性,增加了不必要的复杂性并且容易出错。

问题出在 while (rice < 1000000000, rice *= 2) 条件下。如果多个语句之间用逗号分隔,则整个语句的结果等于最后一个语句的结果。所以你实际上有 while (rice *= 2) 这绝对是真的。

这一行:

while (rice < 1000000000, rice *= 2)

这与您可能认为的不同。 while 循环没有增量部分,所以这是一个逗号表达式,其中第一部分被求值然后被丢弃,第二部分(乘法)是实际结果。这意味着结果是 rice 的新值,转换为布尔值,它始终为真,除非溢出在某个时刻碰巧达到 0。

你要的是

for (; rice < 1000000000; rice *= 2)

您在 while 中使用了复合表达式,就好像它是 "for"

while( rice < 1000000000, rice *= 2)

真值为逗号分隔的两个表达式中的第二个

rice *= 2

是一个非零值,因此为真

两者都

while ( rice < 1000000000) {

      /...
      rice *=2;
}

或使用 for,其中分号的作用符合您的预期

for ( rice = 2; rice < 10000000; rice *= 2 ) {
while (rice < 1000000000, rice *= 2)

这是 comma operator!

的应用程序

这里的意思是:

  • 评估左侧部分,rice < 1000000000,包括所有副作用。
  • rice < 1000000000没有副作用。
  • 舍弃左边的求值结果(即丢弃truefalse)。
  • 评估正确的部分,rice *= 2,所有副作用。
  • 副作用是rice乘以2.
  • 将结果 rice 视为 boolrice 是一个 int,因此除 0 以外的每个值都被视为 true。因此 rice *= 2 的结果总是 true.
  • 整个逗号运算符的结果是右边部分的结果,即true.

所以,问题是你的循环条件是 always true.

(如果这让您感到困惑,请放心,逗号运算符在 C++ 中确实有其用途,但它们往往很少见。)

您的程序的一个可能修复方法是:

#include <iostream>

using namespace std;

int main()
{
  double square = 2;
  double rice = 2;
  while (rice < 1000000000)
  {
    rice *= 2;
    cout << "There is " << rice << " pieces of rice that the inventor owns at square " 
         << square << endl;
    cout << "\n";
    square++;
  }
}

您可以使用for循环来计算需要多少个方块。

int main ()
{
    int grain = 1 ;

    for (int i = 2; i < 65 ; ++i)   // iteration for each of the 64 squares, starting from square 2
    {
        grain += grain ;            // doubling for each of the 64 squares

       if (grain > 1000 && grain < 2000)                // at least 1000 grains of rice
        {
            cout << "square is: " << i << " grains is: " << grain << '\n' ;
        }

        if (grain > 1000000 && grain < 2000000)         // at least 1,000,000 grains
        {
            cout << "square is: " << i << " grains is: " << grain << '\n' ;
        }
        if (grain > 1000000000 && grain < 2000000000)   //at least 1,000,000,000 grains
        {
            cout << "square is: " << i << " grains is: " << grain << '\n' ;
        }
    }

    return 0;

}

我认为这是一个非常古老的问题,但我刚刚开始阅读这本书,这是我的解决方案:

#include "../../std_lib_facilities.h"

int main() {
  int current_square = 1;
  int rice_amount = 1;
  int user_desired_amount = 0;

  cout<<"Enter amount of rice you want to get the number of squares needed: \n";
  cin>>user_desired_amount;

  while(rice_amount <= user_desired_amount) {
    rice_amount *= 2;
    cout<<"rice_amount: "<<rice_amount<<"\n";
    current_square++;
  }
  cout<<"Needed squares are: "<<current_square<<"\n";
  
  return 0;
}

为了测试代码如何响应不同的输入,没有使用固定数字来获得限制。如果您认为这是一种糟糕的方法,我很乐意听取任何意见。提前致谢!