I don’t understand this infini-loop

I’m sorry if this seems very simple to fix, but I encountered something odd when doing what should’ve been a simple while loop. Can anyone help me remedy why this loop goes on forever?

This code was desgined for this simple drill:

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.

Here is my code:

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

If this makes any difference, I rewrote this code to fit into java and got the same thing on eclipse.

Answer

while (rice < 1000000000, rice *= 2)

This is an application of the comma operator!

Its meaning here is:

  • Evaluate the left part, rice < 1000000000, with all side effects.
  • There are no side effects in rice < 1000000000.
  • Discard the evaluation result of the left part (i.e. throw away the resulting true or false).
  • Evalulate the right part, rice *= 2, with all side effects.
  • The side effect is that rice is multiplied by 2.
  • Treat the resulting rice as a bool. rice is an int, so every value other than 0 is considered true. The result of rice *= 2 is therefore always true.
  • The result of the entire comma operator is the result of the right part, i.e. true.

So, the problem is that your loop condition is always true.

(If that’s confusing for you, rest assured that the comma operator does have its uses in C++, but they tend to be rare.)

One possible fix for your program would be:

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