Питон ведет себя по-разному для левого смещения 1 и степени 2 - PullRequest
1 голос
/ 01 октября 2019

Я пытался вычислить 1 << sys.maxsize в моей системе, python сразу выдал мне ошибку памяти, но когда я попытался сделать 2 ** maxsize, python начал вычислять ее без ошибок памяти. Несмотря на то, что 1 << a эквивалентно 2 ** a. (для всех положительных а) </strong> Почему это поведение?

дело 1:

import sys
1 << sys.maxsize

дело 2:

import sys
2 ** sys.maxsize

Результат для дело 1:

---------------------------------------------------------------------------
MemoryError                               Traceback (most recent call last)
<ipython-input-41-0d82f9d0b2eb> in <module>()
----> 1 1 << sys.maxsize

MemoryError: 

Результат для case 2:

# This kept on going without any memory error

1 Ответ

0 голосов
/ 01 октября 2019

2 операции эквивалентны в том смысле, что они дают одинаковый результат.

>>> import sys, math
>>> sys.maxsize, (sys.maxsize + 1) // 8, math.log((sys.maxsize + 1) // 8, 1024)
(9223372036854775807, 1152921504606846976, 6.0)

Как видно выше, ни одна из двух операций не имеет никакого смысла, поскольку (на 64 бит ) результат будет принимать 1EiB ( exbibyte ), что составляет 1048576 (> миллион) TiB ( tebibyte s) !!! , поэтому они оба будут работатьв какой-то момент не хватает памяти.

Согласно [Python 3.docs]: встроенные типы - числовые типы - int, float, complex :

Целые числа имеют неограниченную точность.

В исходном коде ( C ) значение Python int представляется какunsigned short [] ( longintrepr.h ), и 2 функции: long_lshift и long_pow ( [GitHub]: python / cpython - (master)cpython / Objects / longobject.c ).

Это (упрощенная версия) работы двух функций:

  • lshift : попыткивыделить необходимые байты для хранения результата final - который завершается ошибкой (almost мгновенно)
  • pow : выполняет последовательные умножения, увеличивая пространство, необходимое для результата промежуточного (вы можете выдать 2 ** sys.maxsize и посмотреть, как увеличивается используемая память в Диспетчер задач , и если Ctrl + Break в консоли Python , память будет падать).
    Умножение является дорогостоящей ( ЦП и по времени) операцией (даже если для этого есть ускорения), также требуются операции выделения / копирования памяти, поэтому при достаточном времени промежуточный результат будет растипока он не поместится в самый большой доступный блок памяти, и, следовательно, он не будет работать (с той же ошибкой)

Я не уверен, почему для числа 2 (в качестве базы), функция 2 nd не просто вызывает функцию 1 st , но я предполагаю, что дополнительное предложение if будетне оправдывает, поскольку (это приведет к небольшим накладным расходам для всех остальных чисел и) никто не будет / не должен использовать такой безумно большой показатель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...