Что происходит при умножении слишком больших чисел в Python?
Что проверяют
Знаете ли вы, что целые в Python произвольной точности, и, что важнее для работы с данными, где эта гарантия заканчивается. Ответ «переполнения не бывает» без продолжения считается неполным, потому что в пайплайне числа живут не только в чистом Python.
Как отвечать
Тип int растёт по мере надобности, предел только память, поэтому произведение любых двух целых считается точно. Цена этого в скорости: умножение не константная операция, для длинных чисел CPython переключается на алгоритм Карацубы, но время всё равно растёт с длиной операндов, и на факториалах или больших степенях это заметно.
Дальше перечисляем границы, за которыми точность теряется:
numpyиpandasсчитают в фиксированных типах, иint64переполняется молча, превращая сумму или произведение в отрицательное число. Предупреждения может не быть вовсе;- перевод в
floatтеряет точность выше 2 в 53 степени, а на очень больших значениях даётOverflowError. Деление/уводит во float, точным остаётся только//; - у базы свои границы: то, что Python посчитал, в колонку
bigintможет просто не влезть; - перевод очень длинного числа в строку по умолчанию ограничен, лимит поднимается через
sys.set_int_max_str_digits.
Практический вывод: точный счёт денег и идентификаторов держать на int или decimal.Decimal, а в векторных вычислениях явно задавать тип и проверять диапазон заранее.
Где спотыкаются
Переносят правило «в Python переполнения нет» на массивы и датафреймы. Агрегат по колонке int64 уезжает в минус, пайплайн считает дальше как ни в чём не бывало, и ошибка всплывает уже в витрине, где её отделить от бизнес-логики тяжело.
Радуются, что число посчиталось, и отдают его наружу. Сериализация и разбор чисел в тысячи разрядов стоят дорого, а потребитель на стороне интерфейса теряет точность на всём, что больше 2 в 53 степени, поэтому такие значения передают строкой.
Считают большие произведения в лоб там, где нужен не сам результат, а порядок величины или остаток. Сумма логарифмов вместо произведения и pow(a, b, m) вместо ручного возведения в степень с остатком экономят и время, и память.