python 中的逻辑右移 - 表达式的含义 (num % 0x100000000) >> 1

logical right shift in python - meaning of the expression (num % 0x100000000) >> 1

在 java 中,因为我们有 '>>>' 用于逻辑右移操作,而在 Python 中没有。 我遇到过这个表达式:

(num % 0x100000000) >> 1

我正在尝试了解它的工作原理并理解它,这样我就不必死记硬背了。

谢谢

该表达式与逻辑移位和算术移位之间的区别几乎没有关系,后者保留符号(当您谈论二进制补码时最左边的位)。

在您问题的表达式中,num % 0x100000000 只是去掉最右边 32 位左侧的任何内容,以确保您要移动的值被强制转换为 32 位范围 0 - 0xffffffff.然后 >> 1 向右移动。因为你已经强制范围,你将保证得到一个 0 移到最左边的位,即使你的输入值是像 0xffffffff12345678.

这样奇怪的东西

首先,Python 确实有 >> 但没有像 >>> 这样的三重运算符。 >> 按位右移:

https://wiki.python.org/moin/BitwiseOperators

Java 中的 >>> 运算符将位“无符号”右移,这意味着最新的最左边的位始终是 0 位。 (“带符号”移位会复制符号位,因此 0 位用于正整数值,1 位用于负整数值。)

Java 有一个特定大小的变量的概念:你可以有一个 32 位整数,或一个 64 位整数等。在 Python 中我们只有对象类型 int 是任意精度(它们具有所需的存储位,因此可以存储非常大的值)。因此,在您的代码片段中,我们的第一步是确保我们的整数值最大为 32 位。

我不知道你在哪里找到这个例子,但它混合了模运算和 bit-shifting。常数 0x1000000002**32。模数计算除法后剩下的余数。所以这个模运算将只保留整数值的最低 32 位。

就我个人而言,我会使用逻辑与来执行该操作:

x & 0xff_ff_ff_ff(注意下划线在Python3.x中是合法的“糖”;它们什么都不做,但我们可以用它们来分隔数字组。在在这种情况下,我使用它们来分隔字节,以明确这是四个 0xff 字节 st运行g 一起构成 2**32 - 1

此断言不会在我的计算机上触发,因为这两个值相等: assert x & 0xff_ff_ff_ff == x % 0x100000000

但是模数运算符有一个优点:它应该提供数字的低位,无论您 运行 该代码是在“big-endian”计算机还是“[=53=”计算机上编写的]“ 电脑。我使用的是 AMD 64 位处理器,它是 x86,这意味着它是 little-endian。 (我实际上不确定按位与在 big-endian 系统上的 Python 中如何工作;我对 big-endian 系统上的 C 有一些经验,但没有 Python。它可能真的有用!但是模数肯定有用。)

所以,在隔离了值的低 32 位之后,我们想要 right-shift 1 位。我们总是需要注意运算符的优先级,以确保事情以正确的顺序发生;在这种情况下,显式括号保证移位发生在我们只取最低的 32 位之后。

当模取低 32 位时,结果永远不会为负:它将是 00xff_ff_ff_ff 范围内的整数(含)。所以当 right-shifting 高位时肯定是 0 位。因此,此代码片段保证产生与将整数值放入 Java 32 位整数变量然后使用 >>>.

right-shift 相同的结果