簡體   English   中英

旋轉Python中的位

[英]Rotate bits in python

出於好奇,我看到了在字符串域中將對象的id轉換為其哈希的操作,而不是像^|這樣的常規按位操作| & ~

class A:
    pass

def my_hash(a):
    bits = format(id(a), '064b')
    rot4 = bits[-4:] + bits[:-4]
    n = int(rot4, 2)
    return n

for _ in xrange(10):
    a = A()
    print hash(a) == my_hash(a), hash(a), my_hash(a)

但是正如您在下面看到的那樣,下面的功能有時是不正確的。 我想念什么?

>>> run /tmp/thing.py
True 272331835 272331835
False -9223372036582443978 9223372037127107638
True 272331835 272331835
False -9223372036582443978 9223372037127107638
True 272331835 272331835
False -9223372036582443978 9223372037127107638
True 272331835 272331835
False -9223372036582443978 9223372037127107638
True 272331835 272331835
False -9223372036582443978 9223372037127107638

哈希產生一個有符號的整數,您的代碼產生一個無符號的整數。

對於第一個不正確的結果, id(a)值為4357309288 這是0000000000000000000000000000000100000011101101110100001101101000 (64位)。 最后4位為1000 ,將其移到開頭將給出二進制值1000000000000000000000000000000000010000001110110111010000110110 ,當將其解釋為2的補碼有符號整數時為--9223372036582443978 ,因為該位的第一個位(符號位)設置為1

另一方面, int(rot4, 2)始終將輸入解釋為無符號 ,長度無限的整數,因此您將獲得9223372037127107638

Python沒有任何“簡單”選項來將包含二進制數字的字符串解釋為帶符號的整數,您可以使用bitstring庫來簡化操作:

>>> from bitstring import Bits
>>> bits = Bits(int=4357309288, length=64)
>>> bits[-4:]
Bits('0x8')
>>> bits[-4:] + bits[:-4]
Bits('0x80000000103b7436')
>>> (bits[-4:] + bits[:-4]).int
-9223372036582443978L
>>> (bits[-4:] + bits[:-4]).uint
9223372037127107638L

.int.uint為您提供有符號和無符號整數解釋。

使用位bitstring我得到正確的輸出:

>>> def my_hash(a):
...     bits = Bits(int=id(a), length=64)
...     return (bits[-4:] + bits[:-4]).int
...
>>> for _ in xrange(10):
...     a = A()
...     print hash(a) == my_hash(a), hash(a), my_hash(a)
...
True -9223372036585854145 -9223372036585854145
True 268921659 268921659
True -9223372036585854145 -9223372036585854145
True 268921659 268921659
True -9223372036585854145 -9223372036585854145
True 268921659 268921659
True -9223372036585854145 -9223372036585854145
True 268921659 268921659
True -9223372036585854145 -9223372036585854145
True 268921659 268921659

如果您想堅持使用標准庫,請使用此Stack Overflow答案來獲取一個twos_comp()函數:

>>> twos_comp(9223372037127107638, 64)
-9223372036582443978L

那么您的功能將是:

def my_hash(a):
    bits = format(id(a), '064b')
    rot4 = bits[-4:] + bits[:-4]
    n = twos_comp(int(rot4, 2), 64)
    return n

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM