如何在python中获得逻辑右二进制移位

问题描述 投票:0回答:12

如标题所示,JavaScript 中有一个特定的运算符

>>>
。例如,在 JavaScript 中我们将得到以下结果:

(-1000) >>> 3 = 536870787

(-1000) >> 3 = -125

1000 >>> 3 = 125

1000 >> 3 = 125

那么有没有某种方法或运算符可以代表这个

>>>

python bitwise-operators
12个回答
62
投票

没有内置的运算符,但您可以自己轻松模拟

>>>

>>> def rshift(val, n): return val>>n if val >= 0 else (val+0x100000000)>>n
... 
>>> rshift(-1000, 3)
536870787
>>> rshift(1000, 3)
125

以下替代实现消除了对

if
的需要:

>>> def rshift(val, n): return (val % 0x100000000) >> n

11
投票

不,没有。 python 中的右移是算术运算。


3
投票

这是 aix 的答案的衍生内容。如果您向其提供正值,则正常的右移运算符将起作用,因此您实际上正在寻找从有符号到无符号的转换。

def unsigned32(signed):
    return signed % 0x100000000

>>> unsigned32(-1000) >> 3
536870787L

2
投票

尝试通过用 0x100000000 掩码来翻转负数的符号位从根本上是错误的,因为它对字长做出了艰难的假设。在我作为程序员期间,我使用过 24、48、16、18、32、36 和 64 位数字。我还听说过以奇数长度工作的机器,例如 37 和其他使用补码而不是补码算术的机器。除了数字是二进制之外,你对数字的内部表示所做的任何假设都是危险的。

即使二元假设也不是绝对安全的,但我认为我们会允许这种情况。 :)


2
投票

Numpy 提供了

right_shift()
函数来执行此操作:

>>> import numpy
>>> numpy.right_shift(1000, 3)
125

2
投票

您可以使用 >>= 运算符通过 bitstring 模块进行按位移位填充零:

>>> a = BitArray(int=-1000, length=32)
>>> a.int
-1000
>>> a >>= 3
>>> a.int
536870787

1
投票

您需要记住,如果数字为负数,则设置最高位,并且每次向右移位时,您也需要设置最高位。

这是我的实现:

def rshift(val, n):
    s = val & 0x80000000
    for i in range(0,n):
        val >>= 1
        val |= s
    return val

0
投票

无需模数即可工作的解决方案:

>>> def rshift(val,n): return (val>>n) & (0x7fffffff>>(n-1))

这是有效的,因为 7fffffff 是一个正数,右移会在左侧添加零。


0
投票

您还可以使用楼层划分:

def rshift(val, n):
    if val > 0:
        return val >> n
    return val // -(2^n)

-1
投票

这不是一种有效的方法,但效果正如预期的那样

def _toBinary(x):
    x=int(x)
    binary = []
    while x > 0:
        binary.append(str(x%2))
        x=int(x/2)
    return "".join(binary[::-1])

def _fromBinary(xs):
    ans = 0
    for i,x in enumerate(xs[::-1]):
        if x == '1':
            ans += 2**i
    return ans

def leftLogicalShift(x,n=1):
    if not type(x) == int:
        return x
    xs = _toBinary(x)
    xs = [x for x in xs]
    for _ in range(n):
        xs.pop(0)
        xs.append('0')
    return _fromBinary("".join(xs))

def rightLogicalShift(x,n=1):
    if not type(x) == int:
        return x
    xs = _toBinary(x)
    xs = [x for x in xs]
    for _ in range(n):
        xs.pop()
        xs.insert(0,'0')
    return _fromBinary("".join(xs))

def leftArithmeticShift(x,n=1):
    return leftLogicalShift(x,n)

def rightArithmeticShift(x,n=1):
    if not type(x) == int:
        return x
    xs = _toBinary(x)
    xs = [x for x in xs]
    for _ in range(n):
        tmp = xs[0]
        xs.pop()
        xs.insert(0,tmp)
    return _fromBinary("".join(xs))

lls = leftLogicalShift(10,2) 
print(lls) # 8

rls = rightLogicalShift(10,2) 
print(rls) # 2

las = leftArithmeticShift(10,2)
print(las) # 8

ras = rightArithmeticShift(10,2)
print(ras) # 14

参考资料:

https://open4tech.com/ological-vs-arithmetic-shift/

https://www.interviewcake.com/concept/java/bit-shift


-2
投票

投票最高的答案对 val 产生错误的结果 < 0 and n == 0! Here is a correction.

def rshift(val, n):
    if (val >= 0): return val >> n
    elif (n == 0): return val
    else: return (val + 0x10000000) >> n

>>> rshift(-1, 0)
-1

-3
投票

我认为逻辑右二进制移位在Python中不能直接使用。相反,您可以在 Python 中使用 Javascript,如下所示:

import js2py
rshift = js2py.eval_js('function $(a, b){ return a >>> b}')
print (rshift(244, 324)) #15
© www.soinside.com 2019 - 2024. All rights reserved.