Python, длина и размер целых - PullRequest
5 голосов
/ 25 января 2010

Итак, у cPython (2.4) есть интересное поведение, когда длина чего-то приближается к 1 << 32 (размер типа int).</p>

r = xrange(1<<30)
assert len(r) == 1<<30

в порядке, но:

r = xrange(1<<32)
assert len(r) == 1<<32
ValueError: xrange object size cannot be reported`__len__() should return 0 <= outcome

Alex's wowrange также имеет такое поведение.wowrange(1<<32).l хорошо, но len(wowrange(1<<32)) плохо.Я предполагаю, что здесь происходит некоторое поведение с плавающей запятой (читаемое как отрицательное).

  1. Что именно здесь происходит?(это довольно хорошо решено ниже!)
  2. Как я могу обойти это? Длинные?

(Мое конкретное заявление - random.sample(xrange(1<<32),ABUNCH)), если люди хотят заняться этим вопросом напрямую!)

Ответы [ 3 ]

11 голосов
/ 25 января 2010

cPython предполагает, что списки помещаются в память. Это распространяется на объекты, которые ведут себя как списки, такие как xrange. по существу, функция len ожидает, что метод __len__ вернет что-то, что можно преобразовать в size_t, что не произойдет, если число логических элементов слишком велико, даже если эти элементы фактически не существуют в памяти .

5 голосов
/ 25 января 2010

Вы найдете это

xrange(1 << 31 - 1)

- последний, который ведет себя так, как вы хотите. Это связано с тем, что максимальное знаковое (32-разрядное) целое число составляет 2 ^ 31 - 1.

1 << 32 не является 32-разрядным целым числом с положительным знаком (тип Python int), поэтому вы получаете эту ошибку.

В Python 2.6 я даже не могу сделать xrange(1 << 32) или xrange(1 << 31), не получив ошибку, а тем более len в результате.

Редактировать Если вы хотите немного больше деталей ...

1 << 31 представляет число 0x80000000, которое в представлении дополнения 2 является наименьшим представимым отрицательным числом (-1 * 2 ^ 31) для 32-разрядного int. Так что да, из-за побитового представления чисел, с которыми вы работаете, оно на самом деле становится отрицательным.

Для 32-битного номера дополнения до 2 0x7FFFFFFF является наибольшим представимым целым числом (2 ^ 31 - 1) перед тем, как вы «переполнитесь» на отрицательные числа.

Дополнительная информация , если вам интересно.

Обратите внимание, что когда вы видите в приглашении что-то вроде 2147483648L, буква "L" в конце означает, что теперь она представляется как "длинное целое число" (обычно 64 бита, я не могу дать никаких обещаний о том, как Python обрабатывает это, потому что я не читал об этом).

1 голос
/ 25 января 2010

1<<32, если рассматривать его как целое число со знаком, отрицательно.

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