【问题标题】:Python, len, and size of intsPython、len 和整数的大小
【发布时间】:2010-01-24 21:40:33
【问题描述】:

因此,当某物的长度接近 1

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 的wowrange 也有这种行为。 wowrange(1&lt;&lt;32).l 很好,但 len(wowrange(1&lt;&lt;32)) 很糟糕。我猜这里有一些浮点行为(被解读为负面)。

  1. 这里到底发生了什么? (这在下面已经很好地解决了!)
  2. 我怎样才能绕过它? 多头?

(如果人们想直接解决这个问题,我的具体申请是random.sample(xrange(1&lt;&lt;32),ABUNCH))!)

【问题讨论】:

  • @Gregg,很有趣,我得到的是 OverflowError 而不是 ValueError (就像那个 Q 接受的 A 一样),但是,微乎其微。问题是,对于您的特定应用程序,您需要一个无法放入内存的random.sample - 但每个 Python 结构必须 适合内存。如果您打开另一个 Q 并更详细地指定参数,那么提供针对特定应用程序的帮助可能会更实际...
  • @Alex,实际上,样本不必放入内存,但在 2.4(我知道,旧消息!)随机模块中,它执行的 len() 调用失败了! xrange(1
  • random.sample 在 Python 2.5、2.6、3.0 和 3.1 中也需要 to call len(),并且每个版本中的 xrange(1&lt;&lt;32) 调用都失败(因为 len() 仅适用于“适合内存”,而 xrange 在概念上不适合)。因此,如果您更好地指定您到底需要什么,尤其是。 ABUNCH 的典型值是什么,我们可以建议如何解决 random.sample 的限制(适用于 所有 Python 版本!-)。恕我直言,在不同的 Q 中做得更好。
  • @Alex,我只是从 random.sample 方法中抽出胆量,自己编写,因为它非常微不足道。
  • 当然,但如果 ABUNCH 非常大,则需要采取一些预防措施(性能方面)。

标签: python int


【解决方案1】:

cPython 假定列表适合内存。这扩展到行为类似于列表的对象,例如 xrange。本质上,len 函数期望__len__ 方法返回可转换为size_t 的内容,如果逻辑元素的数量太大,即使这些元素实际上不存在于内存中,也不会发生这种情况.

【讨论】:

  • 感谢您解释为什么 len 的行为尤其如此。 cPython len 期望 size_t.
  • 小问题:仅仅因为 size_t 的长度太大并不意味着该对象不适合内存。例如,我有一个表示位字段的类,__len__ 在 32 位 Python 中停止为超过 256MB 的对象工作。
【解决方案2】:

你会发现

xrange(1 << 31 - 1)

是最后一个按照您的意愿行事的人。这是因为最大有符号(32 位)整数是 2^31 - 1。

1 &lt;&lt; 32 不是正符号 32 位整数(Python 的 int 数据类型),所以这就是您收到该错误的原因。

在 Python 2.6 中,我什至无法执行 xrange(1 &lt;&lt; 32)xrange(1 &lt;&lt; 31) 而不会出现错误,更不用说 len 的结果了。

编辑如果你想要更多细节...

1 &lt;&lt; 31 表示数字 0x80000000,它在 2 的补码表示中是 32 位 int 的最低可表示负数 (-1 * 2^31)。所以是的,由于您正在使用的数字的按位表示,它实际上变成了负数。

对于 32 位 2 的补数,0x7FFFFFFF 是您“溢出”为负数之前的最高可表示整数 (2^31 - 1)。

Further reading,如果你有兴趣的话。

请注意,当您在提示中看到类似 2147483648L 的内容时,末尾的“L”表示它现在被表示为“长整数”(通常为 64 位,我无法就 Python 如何处理它,因为我还没有阅读它)。

【讨论】:

  • 试试hex(1 &lt;&lt; 32),看看你会得到什么。提示:它不是 0x80000000。
【解决方案3】:

1&lt;&lt;32,当被视为有符号整数时,为负数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    • 2012-11-07
    • 2019-01-21
    • 2014-01-05
    相关资源
    最近更新 更多