How to Calculate the Average of Digits in a Number in Python
Calculating the average of a number's digits is a common programming exercise. For example, the number 123 has digits 1, 2, and 3, so the average is (1 + 2 + 3) / 3 = 2.0.
This guide covers three approaches: String Conversion for readability, Functional Programming for conciseness, and Pure Math for performance.
Using String Conversion
The most readable approach treats the number as a string of characters, allowing direct iteration over each digit.
def average_of_digits(n: int) -> float:
"""Calculate the average of digits in a number."""
# Handle negative numbers
digits_str = str(abs(n))
# Convert each character to an integer
digits = [int(char) for char in digits_str]
# Calculate and return average
return sum(digits) / len(digits)
print(average_of_digits(842)) # (8 + 4 + 2) / 3 = 4.666...
print(average_of_digits(-123)) # (1 + 2 + 3) / 3 = 2.0
print(average_of_digits(5)) # 5 / 1 = 5.0
Output:
4.666666666666667
2.0
5.0
Handling Edge Cases
def average_of_digits_safe(n: int) -> float | None:
"""Calculate average with edge case handling."""
if n == 0:
return 0.0
digits_str = str(abs(n))
digits = [int(char) for char in digits_str]
return sum(digits) / len(digits)
print(average_of_digits_safe(0)) # 0.0
print(average_of_digits_safe(100)) # (1 + 0 + 0) / 3 = 0.333...
Using Functional Programming
For a more concise solution, use map() to convert characters to integers in a single expression.
def average_of_digits_functional(n: int) -> float:
"""Calculate average using map()."""
digits = list(map(int, str(abs(n))))
return sum(digits) / len(digits)
print(average_of_digits_functional(642)) # 4.0
As a One-Liner
n = 12345
average = sum(map(int, str(abs(n)))) / len(str(abs(n)))
print(f"Average of digits in {n}: {average}")
Output:
Average of digits in 12345: 3.0
Using Pure Math
When performance is critical or memory allocation must be minimized, extract digits using mathematical operations. The modulo operator % gets the last digit, and integer division // removes it.
def average_of_digits_math(n: int) -> float:
"""Calculate average using mathematical operations only."""
n = abs(n)
if n == 0:
return 0.0
total = 0
count = 0
while n > 0:
digit = n % 10 # Extract last digit
total += digit
count += 1
n = n // 10 # Remove last digit
return total / count
print(average_of_digits_math(987)) # (9 + 8 + 7) / 3 = 8.0
print(average_of_digits_math(1000)) # (1 + 0 + 0 + 0) / 4 = 0.25
Output:
8.0
0.25
For n = 123:
123 % 10 = 3→ total = 3, then123 // 10 = 1212 % 10 = 2→ total = 5, then12 // 10 = 11 % 10 = 1→ total = 6, then1 // 10 = 0- Loop ends, return
6 / 3 = 2.0
Extended Example: Statistics on Digits
You can extend this concept to calculate other statistics:
from statistics import mean, median, stdev
def digit_statistics(n: int) -> dict:
"""Calculate various statistics on a number's digits."""
digits = [int(d) for d in str(abs(n))]
stats = {
'digits': digits,
'count': len(digits),
'sum': sum(digits),
'mean': mean(digits),
'median': median(digits),
'min': min(digits),
'max': max(digits),
}
if len(digits) > 1:
stats['stdev'] = stdev(digits)
return stats
result = digit_statistics(9182736)
for key, value in result.items():
print(f"{key}: {value}")
Output:
digits: [9, 1, 8, 2, 7, 3, 6]
count: 7
sum: 36
mean: 5.142857142857143
median: 6
min: 1
max: 9
stdev: 3.132015933791495
Performance Comparison
import time
n = 12345678901234567890
def average_of_digits(n: int) -> float:
"""Calculate the average of digits in a number."""
# Handle negative numbers
digits_str = str(abs(n))
# Convert each character to an integer
digits = [int(char) for char in digits_str]
# Calculate and return average
return sum(digits) / len(digits)
def average_of_digits_math(n: int) -> float:
"""Calculate average using mathematical operations only."""
n = abs(n)
if n == 0:
return 0.0
total = 0
count = 0
while n > 0:
digit = n % 10 # Extract last digit
total += digit
count += 1
n = n // 10 # Remove last digit
return total / count
def average_of_digits_functional(n: int) -> float:
"""Calculate average using map()."""
digits = list(map(int, str(abs(n))))
return sum(digits) / len(digits)
def benchmark(func, n, iterations=100_000):
start = time.perf_counter()
for _ in range(iterations):
func(n)
return time.perf_counter() - start
print(f"String method: {benchmark(average_of_digits, n):.4f}s")
print(f"Functional: {benchmark(average_of_digits_functional, n):.4f}s")
print(f"Math method: {benchmark(average_of_digits_math, n):.4f}s")
Typical Output:
String method: 0.6352s
Functional: 0.5082s
Math method: 0.4151s
The math method is typically fastest for very large numbers because it avoids string allocation. However, for most applications, the difference is negligible and readability should be prioritized.
Method Comparison
| Method | Readability | Performance | Best For |
|---|---|---|---|
| String Conversion | High | Good | General use, clarity |
Functional (map) | High | Good | Concise code |
| Pure Math | Medium | Best | Performance-critical code |
Summary
- Use the string conversion method for most applications: it's readable and handles edge cases clearly.
- Use the functional approach with
map()when you prefer concise, one-liner solutions. - Use the pure math method only when performance is critical or memory allocation must be minimized.