简体   繁体   English

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

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

I'm trying to port some functionality from a Java app to Python. 我正在尝试将一些功能从Java应用程序移植到Python。

In Java, 在Java中

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

Returns: -1694498816 返回:-1694498816

In Python: 在Python中:

print(155 << 24)

Returns 2600468480 返回2600468480

Many other bitwise operations have worked in the same way in both languages. 许多其他按位操作在两种语言中都以相同的方式工作。 Why is there a different result in these two operations? 为什么这两个操作会有不同的结果?


EDIT: I'm trying to create a function in python to replicate how the left shift operator works in Java. 编辑:我正在尝试在python中创建一个函数来复制左移位运算符在Java中的工作方式。 Something along the lines of: 有点像:

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

However this doesn't seem right as (I think) it turns all numbers negatives? 然而,这似乎不正确(我认为)它会使所有数字都变为负数?


EDIT2: Several hours later, I've decided it is probably not the best idea to use Python for this job and will take part of the Java application and use it as a micro service for the existing Python app. 编辑2:几个小时后,我已经决定使用Python来完成这项工作并不是最好的想法,并且会将Java应用程序的一部分用作现有Python应用程序的微服务。

Java has 32-bit fixed width integers, so 155 << 24 shifts the uppermost set bit of 155 (which is bit 7, counting bits from zero, because 155 is greater than 2 7 but less than 2 8 ) into the sign bit (bit 31) and you end up with a negative number. Java具有32位固定宽度整数,因此155 << 24将最高设置位155 (即位7,将位数从零计数,因为155大于2 7但小于2 8 )移位到符号位(第31位)你得到一个负数。

Python has arbitrary-precision integers, so 155 << 24 is numerically equal to the positive number 155 × 2 24 Python具有任意精度的整数,因此155 << 24在数值上等于正数155×2 24

Here are 3 different ways to convert a Python integer to its equivalent Java signed int . 以下是将Python整数转换为等效Java signed int 3种不同方法。 Note that these functions will not work correctly if the argument is wider than 32 bits, so you may wish to use bit masking on the argument before calling them. 请注意,如果参数宽于32位,这些函数将无法正常工作,因此您可能希望在调用参数之前对参数使用位屏蔽。

The first way is to use the struct module to interpret the number as a 32 bit unsigned integer, pack it into bytes (using the local endian convention), and then unpack those bytes, interpreting them as a 32 bit signed integer. 第一种方法是使用struct模块将数字解释为32位无符号整数,将其打包成字节(使用本地字节序约定),然后解压缩这些字节,将它们解释为32位有符号整数。 The other two methods use simple arithmetic with no function calls, so they are faster, but I guess they are a little harder to read. 另外两种方法使用简单的算法而没有函数调用,所以它们更快,但我猜它们有点难以阅读。

This code was written on a 32 bit machine running Python 2.6.6, but it should run correctly on any architecture and version of Python (unless it's extremely ancient :) ). 这段代码是在运行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()

output 产量

 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

Use long in java to get the same result 在java中使用long来获得相同的结果

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

instead of 代替

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

Long are 4 byte length so the precision is the same for this context to python integers. Long是4字节长度,因此对于python整数的上下文,精度是相同的。

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

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