Почему число 2⁶³ занимает 36 байт, а 2⁶³-1 всего 24 байта?

Рассмотрим особенности хранения длинных целых в Python, чтобы разобраться, почему так происходит:

>>> sys.getsizeof(2**63)
36
>>> sys.getsizeof(2**62)
24

В Python все является объектом. Так, размер целого в Python больше, чем обычно:

>>> sys.getsizeof(int())
24

Почему же хранение числа 2⁶³ требует лишние 12 байтов по сравнению с числом 2⁶³ - 1?

В системе LP64 Python-целое состоит из трех фиксированных составляющих размером с указатель:

  • указатель типа;
  • счетчик ссылок;
  • фактическое значение (длинное целое в Си).

Итого 24 байта.

С другой стороны, длинное целое в Python состоит из:

  • указатель типа;
  • счетчик ссылок;
  • количество цифр (целое размером с указатель);
  • встроенный массив цифр значений, каждое из которых занимает по 30 бит значения, но сохраняется в 32-битных единицах (один из незадействованных битов используется для эффективного переноса / записи во время сложения и вычитания).

2⁶³ требует для хранения 64 бита, поэтому число помещается в три 30-битные цифры. Поскольку каждая цифра имеет ширину 4 байта, весь Python long будет принимать 24 + 3 * 4 = 36 байт.

Другими словами, разница возникает из-за длинного целого, которое предполагает отдельное хранение размера числа (8 дополнительных байтов), и поэтому остается меньше места для хранения значения (12 байтов цифр 2⁶³). С учетом размера, хранение значения 2⁶³ в длинном целом занимает 20 байтов. Сравнивая его с 8 байтами, которое занимает любое простое целочисленное значение, получаем 12-байтовую разницу.