问题描述
在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位。
我不知道您在哪里找到此示例,但它是将模运算与位移混合在一起。常数0x100000000
为2**32
。模数找到除法后剩下的余数。因此,该模运算将仅保留整数值的最低32位。
我个人将使用逻辑AND执行该操作:
x & 0xff_ff_ff_ff
(请注意,下划线在Python 3.x中是合法的“糖”;它们不执行任何操作,但是我们可以使用它们来分隔数字组。在这种情况下,我使用它们来分隔字节,以明确表明这是四个0xff
字节串在一起构成的2**32 - 1
此断言不会在我的计算机上触发,因为两个值相等:
assert x & 0xff_ff_ff_ff == x % 0x100000000
但是模运算符有一个优点:无论您是在“大端”计算机还是“小端”计算机上运行该代码,它都应提供数字的低位。我使用的是AMD 64位处理器,即x86,这意味着它是低位优先的。 (我实际上不确定在大型端系统上Python中按位AND的工作方式;我在大型端系统上具有C方面的经验,但在Python上却没有。它可能确实有效!但是模数肯定可以工作。 )
因此,在隔离了值的低32位之后,我们想要右移1位。我们始终需要注意运算符的优先级,以确保事情以正确的顺序进行;在这种情况下,显式括号可确保仅在占用最低的32位之后进行移位。
当模数获取低32位时,结果永远不会为负:它将是一个介于0
到0xff_ff_ff_ff
之间的整数。因此,当右移时,高位肯定会是0
位。因此,保证该代码段产生的效果与将整数值放入Java 32位整数变量然后使用>>>
右移一样。