【问题标题】:Rotate bits in python在python中旋转位
【发布时间】:2015-11-08 20:51:24
【问题描述】:

出于好奇,我看到了在字符串域中将对象的 id 转换为其哈希的操作是什么样的,而不是使用通常的按位操作,如 ^|&、@987654324 @。

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

【问题讨论】:

  • 还有数字触发器,因为每次迭代 Python 都会重用刚刚释放的内存槽; A() 首先分配给内存位置 foo 并绑定到 a,然后下一次迭代新的 A() 分配内存位置 bar,将其重新绑定到 @ 987654330@,此时 foo 上的旧实例被释放(引用计数降至 0,因为 a 不再引用它)。所以下一次迭代A()存储在位置foobar被释放,等等

标签: python hash bit-manipulation bit-shift


【解决方案1】:

哈希产生一个有符号整数,你的代码产生一个无符号整数。

对于您的第一个错误结果,id(a) 值为 4357309288;那是 64 位的 0000000000000000000000000000000100000011101101110100001101101000。最后 4 位是1000,将它们移到开头会得到1000000000000000000000000000000000010000001110110111010000110110 的二进制值,当解释为2's complement signed integer 时为--9223372036582443978,因为第一位,符号位,设置为@987654329 @。

另一方面,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

如果您想坚持使用标准库,请使用this Stack Overflow answer 为自己获取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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-30
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 2019-08-31
    • 1970-01-01
    相关资源
    最近更新 更多