Как проверить максимальное и минимальное значение 64-битного знакового целого числа
Что проверяют
Знаете ли вы, что в Python у int нет фиксированной разрядности, и зачем тогда вообще думать о 64 битах. Следом спрашивают, где эта граница реально всплывает: база, NumPy, передача чисел во фронтенд.
Как отвечать
Сначала сами границы: знаковое 64-битное целое в дополнительном коде хранит значения от -2**63 до 2**63-1, то есть от -9223372036854775808 до 9223372036854775807. Через сдвиг максимум записывается как (1<<63)-1.
Дальше способы проверки, от простого к специальному:
- сравнение:
-2**63 <= x <= 2**63-1, самый читаемый вариант; - упаковка:
x.to_bytes(8, "little", signed=True)иstruct.pack("<q", x)бросают исключение, если число не влезает. Удобно, когда число действительно уходит в бинарный протокол; - NumPy:
np.iinfo(np.int64).maxи.minдают границы без ручной арифметики. В NumPy 2 попытка положить слишком большое Python-число в массивint64даётOverflowError, а вот арифметика над массивами переполняется молча, значения заворачиваются; - ctypes:
ctypes.c_int64(x)молча обрезает значение, для проверки не годится, но хорошо показывает, как поведёт себя код на C.
Потом объясните, зачем это нужно при бесконечном int: колонка BIGINT в PostgreSQL, поля int64 в protobuf, массивы NumPy и pandas. Отдельная ловушка это JSON для фронтенда: в JavaScript безопасные целые заканчиваются на 2**53-1, большие идентификаторы там искажаются, поэтому их отдают строкой.
Где спотыкаются
Называют sys.maxsize максимальным целым. Это максимум Py_ssize_t, от него зависит длина списков и строк, но не размер int: sys.maxsize + 1 прекрасно работает.
Считают через float: 2.0 ** 63 или math.pow(2, 63). Выше 2**53 float теряет точность, и float(2**63-1) == 2**63 возвращает True, граница смазывается.
Говорят, что в Python целые переполняются, как в Java. Сам int не переполняется никогда, переполнение возникает только на стыке с типами фиксированной ширины.