The problem: write a function that sums the digits of a given natural number. For 232 the result is 2 + 3 + 2 = 7.
This exercise comes up constantly when you are learning to program. It is simple, but it teaches you how to split a number into individual digits, a technique you reuse in a lot of other problems.
Method 1: using modulo
<?php
function sumDigit( int $number ): int {
$sum = 0;
while ( $number > 0 ) {
$digit = $number % 10;
$sum += $digit;
$number = intdiv( $number, 10 );
}
return $sum;
}
echo sumDigit( 232 ); // 7
How it works
The whole idea sits in two operations:
$number % 10gives you the last digit. For 232 that returns 2.intdiv( $number, 10 )chops off the last digit. For 232 that gives 23.
Repeat those two steps until the number reaches 0 and you have visited every digit.
Following each iteration with 232 as input:
| Round | $number at start | $digit | $sum | $number at end |
|---|---|---|---|---|
| 1 | 232 | 2 | 2 | 23 |
| 2 | 23 | 3 | 5 | 2 |
| 3 | 2 | 2 | 7 | 0 |
At that point $number is 0, the $number > 0 condition no longer holds, the loop stops and the function returns 7.
A small detail that matters
My first version used this to chop off the last digit:
$number = ( $number - $digit ) / 10;
It gives the right answer, but in PHP the / operator always returns a float, not an int. With small numbers you never notice, but with large numbers a float only holds about 15 to 17 significant digits and starts drifting.
intdiv() performs integer division and always returns an int, so it is both clearer in intent and safer. On PHP older than 7, use (int) ( $number / 10 ) instead.
Method 2: treat it as a string
<?php
function sumDigit( int $number ): int {
return array_sum( str_split( (string) $number ) );
}
Convert the number to a string, split it into characters and add them up. Short and easy to read, since PHP coerces the characters to numbers during addition.
The downside is that it allocates an extra string and an array, so it is slightly slower than method 1. For real-world work that difference is irrelevant.
Method 3: recursion
<?php
function sumDigit( int $number ): int {
if ( $number < 10 ) {
return $number;
}
return ( $number % 10 ) + sumDigit( intdiv( $number, 10 ) );
}
Same idea as method 1, expressed recursively. The base case is when the number is down to a single digit.
Handling negatives and zero
All three return 0 for an input of 0, which is correct. But for negative numbers, methods 1 and 3 return 0 because the loop never runs, while method 2 tries to add the minus sign into the total.
If you want the function to accept negatives, normalise the input up front:
function sumDigit( int $number ): int {
$number = abs( $number );
$sum = 0;
while ( $number > 0 ) {
$sum += $number % 10;
$number = intdiv( $number, 10 );
}
return $sum;
}
Why method 1 is the one to learn
Method 2 is shorter and in real work I would use it. But method 1 is the one worth understanding, because the % 10 and / 10 pair shows up in a lot of other problems: checking whether a number is a palindrome, reversing a number, computing the check digit on a card number with the Luhn algorithm, converting between number bases. Learning it once unlocks a whole family of problems.