繁体   English   中英

为什么逐位移位会在Python和Java中返回不同的结果?

[英]Why does bit-wise shift left return different results in Python and Java?

我正在尝试将一些功能从Java应用程序移植到Python。

在Java中

System.out.println(155 << 24);

返回:-1694498816

在Python中:

print(155 << 24)

返回2600468480

许多其他按位操作在两种语言中都以相同的方式工作。 为什么这两个操作会有不同的结果?


编辑:我正在尝试在python中创建一个函数来复制左移位运算符在Java中的工作方式。 有点像:

def lshift(val, n):
    return (int(val) << n) - 0x100000000

然而,这似乎不正确(我认为)它会使所有数字都变为负数?


编辑2:几个小时后,我已经决定使用Python来完成这项工作并不是最好的想法,并且会将Java应用程序的一部分用作现有Python应用程序的微服务。

Java具有32位固定宽度整数,因此155 << 24将最高设置位155 (即位7,将位数从零计数,因为155大于2 7但小于2 8 )移位到符号位(第31位)你得到一个负数。

Python具有任意精度的整数,因此155 << 24在数值上等于正数155×2 24

以下是将Python整数转换为等效Java signed int 3种不同方法。 请注意,如果参数宽于32位,这些函数将无法正常工作,因此您可能希望在调用参数之前对参数使用位屏蔽。

第一种方法是使用struct模块将数字解释为32位无符号整数,将其打包成字节(使用本地字节序约定),然后解压缩这些字节,将它们解释为32位有符号整数。 另外两种方法使用简单的算法而没有函数调用,所以它们更快,但我猜它们有点难以阅读。

这段代码是在运行Python 2.6.6的32位机器上编写的,但它应该在任何体系结构和Python版本上正确运行(除非它非常古老:))。

from __future__ import print_function
from struct import pack, unpack

def ulong_to_long_pack(u):
    ''' using pack & unpack '''
    ubytes = pack('L', u)
    return unpack('l', ubytes)[0]

def ulong_to_long_sub(u):
    ''' using subtraction '''
    return u - (1<<32) if u >= (1<<31) else u

def ulong_to_long2_xor(u):
    ''' using exclusive OR '''
    return u ^ ~((1<<32)-1) if u & (1<<31) else u

funcs = (ulong_to_long_pack, ulong_to_long_sub, ulong_to_long2_xor)

# test
for ulong_to_long in funcs:
    print(ulong_to_long.__doc__)

    u = 2600468480
    print(u, ulong_to_long(u))

    big = 1<<31
    for u in range(big - 3, big + 3):
        print(u, ulong_to_long(u))

    print()

产量

 using pack & unpack 
2600468480 -1694498816
2147483645 2147483645
2147483646 2147483646
2147483647 2147483647
2147483648 -2147483648
2147483649 -2147483647
2147483650 -2147483646

 using subtraction 
2600468480 -1694498816
2147483645 2147483645
2147483646 2147483646
2147483647 2147483647
2147483648 -2147483648
2147483649 -2147483647
2147483650 -2147483646

 using exclusive OR 
2600468480 -1694498816
2147483645 2147483645
2147483646 2147483646
2147483647 2147483647
2147483648 -2147483648
2147483649 -2147483647
2147483650 -2147483646

在java中使用long来获得相同的结果

System.out.println(155L << 24);

代替

System.out.println(155 << 24);

Long是4字节长度,因此对于python整数的上下文,精度是相同的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM