Before arrays, before anything with a name, there is this: getting at the digits of a number.
It looks like a trick the first time and then turns out to be the same trick every time.
The two operations#
For any whole number n:
n % 10gives its last digitn / 10, with the remainder thrown away, removes that digit
For 4071:
| n | n % 10 | n / 10 |
|---|---|---|
| 4071 | 1 | 407 |
| 407 | 7 | 40 |
| 40 | 0 | 4 |
| 4 | 4 | 0 |
Four steps and the number is gone. That is the loop:
while n > 0:
digit = n % 10
... do something with digit ...
n = n / 10
Integer division is the part to be careful about. In C, C++ and Java, 407 / 10 is 40 because the type is an integer and the fraction is discarded. In Python / gives 40.7, and you must write // instead. Same idea, different symbol.
Why it is worth learning properly#
Change the one line in the middle and you have solved a different problem:
| Do this to each digit | And you have |
|---|---|
| add one to a counter | count the digits |
| add it to a running total | digit sum |
result = result * 10 + digit | the number reversed |
| raise it to the power of the digit count and total | an Armstrong number check |
| compare the reversed number with the original | a palindrome check |
Six problems, one loop. That is why this comes first.
Building a number back up#
Reversing needs the opposite move. Where % 10 and / 10 take digits off the right, this puts them on:
result = result * 10 + digit
Reversing 407:
| digit taken | result before | result after |
|---|---|---|
| 7 | 0 | 7 |
| 0 | 7 | 70 |
| 4 | 70 | 704 |
Multiplying by ten shifts everything left and leaves a space, and adding the digit fills it.
Zero, and other awkward cases#
Zero. The loop while n > 0 never runs, so a count of digits comes out as 0 when the answer should be 1. Nearly every digit problem needs zero considered on its own.
Negative numbers. In most languages -407 % 10 is -7, not 3. If negatives are possible, take the absolute value first and remember the sign.
Overflow. Reversing a large number can produce one too big for the type. 2147483647 reversed does not fit in a 32 bit integer. Where a problem allows large input, use a 64 bit type.
The cost#
A number with d digits takes d steps, and d is about log10(n). So this is O(log n), which for any number you can type is a handful of steps. Turning the number into text and looping over the characters also works and is often slower and more memory, though it is perfectly reasonable when clarity matters more.
Common mistakes#
- Using
/in Python where//is meant, so the loop never ends. - Forgetting zero.
- Assuming
%gives a positive answer for a negative number. - Reversing into a type too small to hold the result.