【问题标题】:confusion in left shift operator in pythonpython中左移运算符的混淆
【发布时间】:2014-01-28 12:10:48
【问题描述】:

我正在尝试对整数的 16 位二进制表示使用左移运算符

编写的代码如下:

def showbits(x):
    return bin(x)[2:].zfill(16)
i=5225
print "Decimal %d is same as binary" % (i)
print showbits(i)
for j in range(0,5,1):
    k=i<<j
    print "%d right shift % gives" % (i,j)
    print showbits(k)

输出:

Decimal 5225 is same as binary
0001010001101001
5225 right shift  0ives
0001010001101001
5225 right shift  1ives
0010100011010010
5225 right shift  2ives
0101000110100100
5225 right shift  3ives
1010001101001000
5225 right shift  4ives
10100011010010000

主要问题是当它移动前导“1”时,它并没有消失,而是增加了一位......

有什么解决办法吗?

【问题讨论】:

  • 我很好奇你为什么要用像 python 这样的高级语言来做奇怪的位移?
  • @wim:因为有时您需要对值进行位移。例如,当与向您发送包含标志的字节的其他系统进行互操作时。每个人都试图解析二进制格式?另一个用途是将一个值乘以 2 的指数。
  • @wim 例如,我正在实现 dns 数据包解析器并猜测,我需要使用位进行操作。对我来说这很奇怪,在语言 X 中你不应该做 Y 因为它是语言 X !只是愚蠢...

标签: python bit-manipulation


【解决方案1】:

你会屏蔽结果值,用&amp;按位与:

mask = 2 ** 16 - 1
k = (i << j) & mask

这里16是你想要的位宽;您可以使用i.bit_length() 将其限制为i 所需的最小大小,但这意味着任何 左移都会丢失位。

掩码形成一系列与原始值宽度相同的1位; &amp; 操作将任何位设置为 0 在这些之外

>>> 0b1010 & 0b111
2
>>> format(0b1010 & 0b111, '04b')
'0010'

一些旁注:

  • 向左移动,而不是向右移动。
  • 您似乎忘记了调试打印中的d

    print "%d left shift %d gives" % (i,j)
    

    那里有一个单独的%,它与ggives 组合成%g(浮点格式)。

  • 你可以使用:

    def showbits(x):
        return format(x, '016b')
    

    将整数格式化为 0 填充的 16 个字符宽的二进制表示形式没有0b 前缀。

【讨论】:

  • @Kroltan:因为这是将值限制为特定位宽的标准按位运算。
  • 它给出错误:** 或 pow() 不支持的操作数类型:'int' and 'builtin_function_or_method'
  • @user3223301:抱歉,这是一个错误,刚才 SO 的中断让我无法为您修复。
  • 哦,那么 Python 会自动扩展数字的位宽以适应所有信息吗?很有趣。
  • 是的,python 是一个具有非固定 int 类型的坏人,因为我需要编写 14 位掩码来削减 2 个高位 =(
【解决方案2】:

因为 Python 做了一些魔法来防止这种情况(称为溢出)的发生。它通过调整类型来做到这一点:

>>> i = 5225
>>> type(i)
<type 'int'>
>>> j = i << 16; type(j); bin(j)
<type 'int'>
'0b10100011010010000000000000000'
>>> j = i << 32; type(j); bin(j)
<type 'int'>
'0b101000110100100000000000000000000000000000000'
>>> j = i << 64; type(j); bin(j)
<type 'long'>
'0b10100011010010000000000000000000000000000000000000000000000000000000000000000'
>>> j = i << 128; type(j); bin(j)
<type 'long'>
'0b101000110100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'

如果您想限制要使用的位,请按照 Martijn 的建议进行操作并使用 16 位掩码。

>>> j = 0xffff & (i << 12); type(j); bin(j)[2:].zfill(16)
<type 'int'>
'1001000000000000'
>>> j = 0xffff & (i << 13); type(j); bin(j)[2:].zfill(16)
<type 'int'>
'0010000000000000'
>>> j = 0xffff & (i << 14); type(j); bin(j)[2:].zfill(16)
<type 'int'>
'0100000000000000'
>>> j = 0xffff & (i << 15); type(j); bin(j)[2:].zfill(16)
<type 'int'>
'1000000000000000'
>>> j = 0xffff & (i << 16); type(j); bin(j)[2:].zfill(16)
<type 'int'>
'0000000000000000'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多