Как найти сумму цифр числа в Python? Разбор подходов

Раздел: Числа -> Работа с цифрами числа

Способы нахождения суммы цифр числа

Наиболее эффективное решение основано на делении числа на 10 в цикле. Оно не требует преобразования в строку и работает только с целыми числами.

def sum_digits_math(n):
    total = 0
    n = abs(n)  # учёт знака
    while n > 0:
        total += n % 10
        n //= 10
    return total

print(sum_digits_math(12345))  # 15
print(sum_digits_math(-987))   # 24

Python найти сумму цифр числа (нахождение суммы цифр числа в python)

Пояснения:

Переменная total накапливает сумму. На каждой итерации берём последнюю цифру через остаток от деления на 10 (n % 10), затем отбрасываем её целочисленным делением (n //= 10). Цикл продолжается, пока число не станет равным нулю. Функция корректно обрабатывает отрицательные числа благодаря abs().

Возможные проблемы:

  • Для числа 0 функция вернёт 0, что логично.
  • Слишком большие числа (например, 10^100) обрабатываются корректно, так как Python поддерживает длинную арифметику.
  • Числа с плавающей точкой требуют предварительного преобразования в целое или отдельной логики.

Как найти сумму цифр числа, используя строковое представление?

def sum_digits_str(n):
    return sum(int(d) for d in str(abs(n)))

print(sum_digits_str(12345))  # 15
print(sum_digits_str(-987))   # 24

Пояснения:

Функция преобразует число в строку (str(abs(n))), после чего генератор перебирает каждый символ, превращая его в целое число через int(). sum() складывает полученные цифры. Код компактен, но менее производителен из-за операций со строками.

Возможные проблемы:

  • Для очень больших чисел преобразование в строку может потребовать дополнительной памяти.
  • Если число отрицательное, знак минуса не станет частью цифр (благодаря abs()).

Цели и случаи использования:

Вариант удобен для быстрого написания кода, когда важна читаемость, а производительность не критична. Подходит для чисел любой длины.

Как реализовать рекурсивную функцию для подсчёта суммы цифр?

def sum_digits_rec(n):
    n = abs(n)
    if n < 10:
        return n
    return n % 10 + sum_digits_rec(n // 10)

print(sum_digits_rec(12345))  # 15
print(sum_digits_rec(-987))   # 24

Пояснения:

Базовое условие: если число меньше 10, возвращаем его как последнюю цифру. Иначе складываем последнюю цифру (n % 10) и рекурсивно вызываем функцию для усечённого числа (n // 10).

Возможные проблемы:

  • Глубина рекурсии ограничена (по умолчанию ~1000). Для чисел с более чем 1000 цифр возникнет RecursionError.
  • Решение не подходит для production-кода с непредсказуемо большими числами.

Цели и случаи использования:

Рекурсия демонстрирует математическую природу задачи. Полезна в учебных целях и при небольших числах.

Как применить map и sum для вычисления суммы цифр?

def sum_digits_map(n):
    return sum(map(int, str(abs(n))))

print(sum_digits_map(12345))  # 15
print(sum_digits_map(-987))   # 24

Пояснения:

Функция map применяет int к каждому символу строки, затем sum суммирует результаты. Этот вариант немного быстрее генератора, но принцип тот же.

Возможные проблемы:

Те же, что и для строкового подхода (память при больших строках).

Цели и случаи использования:

Краткая запись, подходящая для встраивания в однострочные выражения.

Как обработать отрицательные числа и числа с плавающей точкой?

def sum_digits_float(n):
    # для отрицательных чисел убираем знак
    n = abs(n)
    # разбиваем на целую и дробную части
    s = str(n)
    if '.' in s:
        # удаляем десятичную точку, суммируем все цифры
        digits = s.replace('.', '')
        return sum(int(d) for d in digits)
    else:
        return sum(int(d) for d in s)

print(sum_digits_float(123.45))   # 1+2+3+4+5 = 15
print(sum_digits_float(-7.89))    # 7+8+9 = 24

Пояснения:

Функция преобразует число в строку, убирает десятичную точку (если есть) и суммирует все цифровые символы. Знак отбрасывается через abs(). Недостаток: экспоненциальная запись (1e-5) не обрабатывается.

Возможные проблемы:

  • Числа в научной нотации (например, 1.23e4) приведут к неверному результату.
  • Строковое представление может содержать лишние нули после запятой в некоторых версиях Python.

Цели и случаи использования:

Подходит, когда нужно суммировать все десятичные цифры числа как целого (без учёта порядка).

Как найти сумму цифр без преобразования в строку и без цикла while? (математический)

import math

def sum_digits_log(n):
    n = abs(n)
    if n == 0:
        return 0
    total = 0
    # количество цифр
    num_digits = int(math.log10(n)) + 1
    for i in range(num_digits):
        total += n % 10
        n //= 10
    return total

print(sum_digits_log(12345))  # 15

Пояснения:

Здесь используется math.log10 для определения количества цифр, а затем цикл for вместо while. Способ менее эффективен из-за вызова логарифма и возможной погрешности с плавающей точкой для больших чисел.

Возможные проблемы:

  • Для числа 0 требуется отдельная проверка.
  • Для чисел с большим количеством цифр (например, 10^308) log10 может дать неточный результат из-за округления float.

Цели и случаи использования:

Демонстрация альтернативного математического подхода. Не рекомендуется для реальных проектов.

Расширенные примеры

Пример 1. Сумма цифр для списка чисел

Пример
def sum_digits_math(n):
    total = 0
    n = abs(n)
    while n:
        total += n % 10
        n //= 10
    return total

numbers = [123, -456, 7890, 0, 100200]
sums = [sum_digits_math(num) for num in numbers]
print(sums)  # [6, 15, 24, 0, 3]
[6, 15, 24, 0, 3]

Пояснения:

Генератор списка применяет функцию к каждому элементу. Подходит для массовой обработки данных.

Пример 2. Сумма цифр в различных системах счисления

Пример
def sum_digits_base(n, base):
    """Сумма цифр числа n в системе счисления base (base > 1)"""
    if n == 0:
        return 0
    n = abs(n)
    total = 0
    while n > 0:
        total += n % base
        n //= base
    return total

print(sum_digits_base(255, 2))   # двоичная: 11111111 -> 8
print(sum_digits_base(255, 16))  # шестнадцатеричная: FF -> 15+15=30
print(sum_digits_base(1234, 10)) # десятичная как обычно
8
30
10

Пояснения:

Вместо деления на 10 используется деление на основание системы. Пригодится для анализа цифровых корней в нестандартных основаниях.

Пример 3. Использование reduce для суммирования цифр

Пример
from functools import reduce

def sum_digits_reduce(n):
    return reduce(lambda acc, ch: acc + int(ch), str(abs(n)), 0)

print(sum_digits_reduce(54321))  # 15
15

Пояснения:

Функция reduce последовательно применяет лямбда-функцию, накапливая сумму. Подход функционального стиля, хотя и менее читаемый.

Пример 4. Измерение производительности различных методов

Пример
import timeit

def sum_math(n):
    total = 0
    n = abs(n)
    while n:
        total += n % 10
        n //= 10
    return total

def sum_str(n):
    return sum(int(d) for d in str(abs(n)))

def sum_map(n):
    return sum(map(int, str(abs(n))))

num = 12345678901234567890
for func in (sum_math, sum_str, sum_map):
    t = timeit.timeit(lambda: func(num), number=100000)
    print(f"{func.__name__}: {t:.5f} sec")
sum_math: 0.24567 sec
sum_str: 0.31245 sec
sum_map: 0.28912 sec

Пояснения:

Математический способ (while) обычно быстрее, так как не использует строковые операции. Приведённые числа зависят от версии Python и железа.

Пример 5. Сумма цифр числа, заданного строкой (например, из файла)

Пример
def sum_digits_from_string(s):
    """s - строка, содержащая только цифры и, возможно, знак"""
    # удаляем знак минуса, если есть
    s = s.lstrip('-')
    return sum(int(ch) for ch in s if ch.isdigit())

print(sum_digits_from_string('-12345'))  # 15
print(sum_digits_from_string('98765'))   # 35
# с посторонними символами не сработает корректно
15
35

Пояснения:

Полезно, когда число получено как строка (например, из CSV-файла). Проверка isdigit() отсеивает нецифровые символы, но может пропустить десятичную точку.

Пример 6. Рекурсия с мемоизацией (для серии вызовов)

Пример
from functools import lru_cache

@lru_cache(maxsize=None)
def sum_digits_memo(n):
    n = abs(n)
    if n < 10:
        return n
    return n % 10 + sum_digits_memo(n // 10)

print(sum_digits_memo(12345))  # 15
print(sum_digits_memo(67890))  # 30
# повторный вызов с тем же значением берётся из кэша
15
30

Пояснения:

Декоратор lru_cache запоминает результаты для уже вычисленных чисел. Ускоряет повторные вызовы, но глубина рекурсии остаётся ограничением.

Пример 7. Поиск чисел с заданной суммой цифр (например, все трёхзначные с суммой 15)

Пример
def numbers_with_sum(sum_target, digits_count):
    result = []
    start = 10 ** (digits_count - 1)
    end = 10 ** digits_count - 1
    for num in range(start, end + 1):
        if sum(int(d) for d in str(num)) == sum_target:
            result.append(num)
    return result

print(numbers_with_sum(15, 3)[:10])  # первые 10 трёхзначных с суммой 15
[159, 168, 177, 186, 195, 249, 258, 267, 276, 285]

Пояснения:

Пример комбинаторного использования суммы цифр. Для больших диапазонов лучше применить генерацию комбинаций.

Нахождение суммы цифр числа в Python - comments

En
Python найти сумму цифр числа (python)