33

I am having trouble understanding how exactly this code works:

int length = 1;
int x = 234567545;
while (x /= 10)
   length++;

It is supposed to count the number of digits in the int variable. I don't get how the while loop is working. Does the loop just go to zero and stop by default? Also, why is the length starting at 1?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
VickTree
  • 889
  • 11
  • 26
  • 1
    Zero means false. Think about that regarding how that loop ends. The final iteration (where `x < 10` is true), will break the loop, but not account for that final digit, thus the starting point of `1` requirement. – WhozCraig Jan 10 '19 at 20:55
  • 15
    Step through your program with a debugger and *watch* the value of the `x` variable. BTW, `/=` means `x = x / 10`. – Thomas Matthews Jan 10 '19 at 20:56
  • 5
    As an aside: a simpler way to get the number of digits for a positive number is `ceil(log10(x))`. –  Jan 10 '19 at 21:02
  • [For other approaches, see this instead](https://stackoverflow.com/questions/6601592/counting-digits-using-while-loop). – user202729 Jan 11 '19 at 06:19
  • 4
    @duskwuff … and get a crash when x <= 0, and the wrong answer when x = 10, 100, 1000, etc. – alephzero Jan 11 '19 at 09:30
  • If you still don't get it, it is the same as `x = x / 10; while ( x != 0 ) { length++; x = x / 10; }` – Spikatrix Jan 11 '19 at 11:29
  • 4
    Why is this question off-topic? – Peter Mortensen Jan 11 '19 at 13:36
  • 3
    @PeterMortensen I agree. The reason given is off-topic if anything. OP didn't ask for recommendations regarding books or tools etc. – Ted Lyngmo Jan 12 '19 at 11:37
  • I'm voting to reopen this question because I don't think it should have been closed for being off-topic – William Miller Jan 12 '20 at 00:36

6 Answers6

57

There are three things that might be suspicious for you if you are a C++ beginner:

First thing might be operator /=, which combines an integral division (i.e. without remainder), with an assignment. So x /= 10 actually is the same as x = x / 10.

Second, each expression in C++ has - after having been evaluated - a value. For an assignment like (x = 0), the result is the value of x after the assignment, i.e. 0 in this case.

Third, a condition like if (x) ... with x being of integral type has in C++ the same meaning as if(x != 0), i.e. it is false if x equals 0, and it is true if x is anything else but 0.

All together: while ( x /= 10 ) means assign x the value of an integral division by 10 and then compare the value to 0. If 0 is reached, the loop ends.

BTW: length starts with 1, because any number, even 0, comprises at least one digit.

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
27

x /= 10 continuously divides x by 10, which will make it 0 eventually and cause the while loop to terminate due to 0 being interpreted as false (and any other value than 0 as true).

The reason it starts at length = 1 is because there is always at least 1 digit in the number: if x was from 0 to 9 inclusive, then x /= 10 would cause x to become 0 immediately, meaning nothing inside the loop would execute. Therefore, if length started at 0, it would never get to be incremented to 1 which would be wrong if x was a single digit large.

Manually calculating this example by hand:

  1. 234567545 / 10 = 23456754, which is true, so the while loop continues and length becomes 2.

  2. 23456754 / 10 = 2345675, true. length becomes 3.

  3. 2345675 / 10 = 234567, true. length becomes 4.

  4. 234567 / 10 = 23456, true. length becomes 5.

  5. 23456 / 10 = 2345, true. length becomes 6.

  6. 2345 / 10 = 234, true. length becomes 7.

  7. 234 / 10 = 23, true. length becomes 8.

  8. 23 / 10 = 2, true. length becomes 9.

  9. 2 / 10 = 0, false. The while loop stops with length equal 9.

brothir
  • 694
  • 6
  • 14
8

The loop

while (x /= 10) {
  length++;
}

will go until the result of x /= 10 evaluates to false, since 0 means false it will go until x /= 10 is 0. Integer division truncates, ensuring the condition will be reached. This can be illustrated by adding a simple debug statement, i.e.

while (x /= 10) {
  length++;
  std::cout << length << " " << x << std::endl;
}

Which outputs

2 23456754
3 2345675
4 234567
5 23456
6 2345
7 234
8 23
9 2
William Miller
  • 9,839
  • 3
  • 25
  • 46
6

Integer division will truncate the remainder, so continually dividing a number with integer division will inevitably result in zero.

Dividing a number n by 10 while incrementing a counter i once for each time the resulting quotient (stored back into n) is not zero will result in the i containing the number of digits for the base-10 representation of n.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
5

It helps to understand two parts:

  • what is "/="
  • when does the loop terminate

Explain "/="

This:

x /= 10

is the same as:

x = x / 10

Explain when the loop terminates

The while loop terminates, when the condition is false. And 0 is equivalent to false.

while (condition) {
    length++;
}

So x is, with every pass through the loop, divided by 10, until is is 0. That terminates the loop.

So, the condition is two things at the same time:

  • it is a value, that is compared to 0. The loop continues until this evaluates to 0.
  • it is an assignment: x gets a new value with every evaluation. It's divided by 10, so it converges to 0.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jörg Beyer
  • 3,631
  • 21
  • 35
-11

This is a bit of stupidity you'll often see in C/C++, taking advantage of the fact that TRUE is implemented as non-zero, and FALSE as zero*. So x is repeatedly divided by 10, and the expression eventually becomes zero, so the loop stops.

Though confusing, this works - until the day someone in a hurry changes x from an int to a double :-) Much clearer and less failure-prone to write "while (x /= 10 >= 1)", or even to put the math inside the loop body rather than in the condition.

*IMHO one of the few shortcomings of C is that it didn't have an explicit logical type, as FORTRAN did.

jamesqf
  • 215
  • 2
  • 4
  • 12
    It would be best if you keep the rants about what you don't like in C++ out of your answer... – user202729 Jan 11 '19 at 06:19
  • 14
    1) Rather too opinionated. 2) Absolutely not limited to C/C++, but rather common to a lot of programming languages. 3) To catch things like "someone changing a type in a hurry" (and you should never change working code "in a hurry"), we're writing and executing tests. 4) Contracting logic into a condition like that is not at all confusing to anyone but a beginner at programming. (Next thing you argue about zero-based indexing...) 5) Question is C++, not C, and C++ *does* have an explicit logical type (as does C since C99). – DevSolar Jan 11 '19 at 08:06
  • 5
    6) Your "fix" doesn't work with negative numbers. 7) Code counts number of digits in an int, which is undefined for a double anyway. – pipe Jan 11 '19 at 10:45
  • 6
    Your change does not work, because `>=` has higher precedence ( https://en.cppreference.com/w/cpp/language/operator_precedence) than `/=`. So, `10 >= 1` is evaluated to `1`, and `x /= 1` leaves the value of `x` unchanged, leading to an infinite loop. – kfx Jan 11 '19 at 12:03