математика
February 12

Решение задач с разбиением чисел на цифры

Часто в задачах требуется не просто оперировать числом как целым, а разложить его на отдельные цифры — как разобрать механизм на детали. Рассмотрим простой, но эффективный подход.

Для этого вспомним, что мы можем подсчитать целую и остаточную части при делении на 10 (или другое число, смотря в какой системе счисления работаем).

Допустим, имеем задачу:

"Дано 32-битное знаковое целое число x. Верните x с перевернутыми цифрами. Если переворачивание x приводит к выходу значения за пределы диапазона 32-битных знаковых целых чисел [-2**31, 2**31 - 1], верните 0"

Ключевая часть алгоритма к решению может выглядеть так - итеративно, пока целая часть от деления на 10 не равна 0 берем дробную и добавляем к результату, умноженному на 10:

def f(x):

    num = 2**31
    min_x = -num
    max_x = num - 1

    if x<0:
        sign = -1
        x = -x
    else:
        sign = 1

    res = 0

    while x!=0:
        ost = x%10
        x = x//10
        res = res*10 + ost

        if (res<min_x) or (res>max_x):
            return 0

    return res*sign

f(123)

Чтобы не мучиться с остатком, посчитаем знак и будем работать с положительным x. Напомню, что остаток в Python имеет знак делителя и работает правило:

a % b = a - b * floor(a / b),

floor(a / b) — округление вниз до ближайшего целого.

7%3 = 7 - 3*2=1

7%-3 = 7 + 3(-3) = -2

-7%-3 = -7 + 3*(2) = -1

-7%3 = -7 - 3*(-3)=2

Логика аналогичная, если надо положительное целое из десятичной перевести в двоичную систему:

x = 123
s = ''
while x!=0:
    ost = x%2
    s = f'{ost}{s}'
    x  = x//2

и обратно:

res = 0
s_len = len(s)
for i, num in enumerate(s):
    res = res + int(num)*2**(s_len-1-i)
res