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。常数 0x100000000
是 2**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 位时,结果永远不会为负:它将是 0
到 0xff_ff_ff_ff
范围内的整数(含)。所以当 right-shifting 高位时肯定是 0
位。因此,此代码片段保证产生与将整数值放入 Java 32 位整数变量然后使用 >>>
.
right-shift 相同的结果
在 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。常数 0x100000000
是 2**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 位时,结果永远不会为负:它将是 0
到 0xff_ff_ff_ff
范围内的整数(含)。所以当 right-shifting 高位时肯定是 0
位。因此,此代码片段保证产生与将整数值放入 Java 32 位整数变量然后使用 >>>
.