如何看待Python的负数按位运算?

Eul*_*ity 4 python bit-manipulation negative-number python-3.x

我发现很难思考 Python(和 Python3)的无限精度负数和按位运算。它不是 32 位或 64 位。1左边的 s 可以被认为是“无穷多个” 。它不是很明确,这就是为什么有时很难思考它是如何运作的。

似乎一种可行的方法是:总是让它更多,例如如果您正在处理具有 67 位的正整数,那么只需考虑它们与具有 96 位或 128 位的负数的运算即可。这是正确的思考方式吗?规格中是否有任何说明其工作原理或应考虑的内容?(比如内部实现只考虑正整数,而只考虑负数“向左多1位”?)

kay*_*ya3 8

您应该将它们视为具有无限多个 1 位。抽象来说,二进制补码表示无限多个1;并不是说可以根据需要添加更多的 1,而是这些 1已经成为数字表示方式的一部分。

\n\n

事实上,那些无限多的位实际上并未存储在内存中,这是一个实现细节,因此,当您考虑这一点时,您应该忽略内存的限制,直到您遇到必须这样做的情况。写出实现。如果您只是想从概念上理解这一点,则不需要考虑诸如后备位之类的事情,而且我认为这不一定有帮助。

\n\n
\n\n

二进制数表示 2 的幂之和,例如:

\n\n
\n

11001 2 = 2 4 + 2 3 + 0 + 0 + 2 0

\n
\n\n

数字 -1 由无限的 1 序列表示,向左无限延伸:

\n\n
\n

...1111 2 = ... + 2 3 + 2 2 + 2 1 + 2 0

\n
\n\n

这对于通常意义上的无穷级数来说是无稽之谈,但有充分的理由将结果定义为 -1。最直观地吸引人的原因是当你按照加法算法将 1 添加到它时会发生什么:

\n\n
  ...111111111\n+            1\n  \xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\n= ...000000000 (result)\n  \xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\n  ...11111111  (carry)\n
Run Code Online (Sandbox Code Playgroud)\n\n

在最右边的列中,您有 1 + 1,即 2,或二进制的10 2 ,因此您写入 0 并将 1 传送到左侧的下一列。然后在该列中你有一个 1 加上进位 1,所以你写 0 并进位另一个 1...等等,无穷无尽。结果每个位置都有 0。因此,...11111 2一定代表 -1,因为我们按照算法加 1,得到了 0 的表示。

\n\n

如果这还不够令人满意,那么还有其他原因......11111 2应该被解释为 -1 的表示:

\n\n
    \n
  • 无限和 1 + 2 + 4 + 8 + ... 是一个几何级数;具有恒定比率 r 的几何级数的公式为 1/(1 - r)。该公式仅适用于 -1 < r < 1 时,但如果我们无论如何代入 r = 2,那么我们确实会得到结果 -1。
  • \n
  • 无限和 1 + 2 + 4 + 8 + ... 实际上在2-进范数中收敛到 -1 。
  • \n
  • 结果 -1 也可以通过包括欧拉求和在内的其他定义获得,并且正如维基百科所述,任何既稳定线性的求和方法都会将该和与结果 \xe2\x88\x9e 或 -1 相关联。
  • \n
\n\n

我提到这些还因为它们暗示某些性质对于算术仍然成立。应用“无穷大”的加法、减法和乘法的常用算法可以给出符合算术常用属性(如结合性、交换性和分配性)的合理结果。

\n