簡體   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