首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在python中对符号值和无符号值进行算术右移

如何在python中对符号值和无符号值进行算术右移
EN

Stack Overflow用户
提问于 2020-11-23 05:50:31
回答 3查看 8K关注 0票数 7

一些语言,如Java,Verilog都有按位逻辑(<<,>>)和算术移位(<<<,>>>)操作符。

对于无符号值,逻辑移位和算术移位具有相同的操作。假设8‘b 11000101是8位无符号数197的二进制表示,那么

代码语言:javascript
复制
8'b11000101 >>  2 => 8'b00110001
8'b11000101 >>> 2 => 8'b00110001
8'b11000101 <<  2 => 8'b00010100
8'b11000101 <<< 2 => 8'b00010100

对于有符号值,只有算术和逻辑左移位操作是相同的,但是算术右移位导致符号扩展。假设8‘b 11000101是8位有符号数字-59的二进制表示,那么

代码语言:javascript
复制
8'b11000101 >>  2 => 8'b00110001
8'b11000101 >>> 2 => 8'b11110001
8'b11000101 <<  2 => 8'b00010100
8'b11000101 <<< 2 => 8'b00010100

Python只有逻辑移位操作符,但没有算术移位运算符。那么,如何在python中实现签名值和无符号值的算术右移呢?

EN

回答 3

Stack Overflow用户

发布于 2020-11-24 12:59:46

只有逻辑移位操作符,但没有算术移位运算符。那么,如何在python中实现签名值和无符号值的算术右移呢?

Python实际上只有算术移位操作符:

  • 左移与n的2乘乘幂n完全相同,两者均为负值,
  • 的右移取决于被移动的值是否为负值。正值除以n的幂,然后四舍五入到0,而负值表现为在最重要的位侧有无限串的1位,这是两个负数的补码表示的副作用。这转化为一个单一的数学等价:用一个正的积分量将一个整数右移为2除以Math.floor(value / 2**n)

的平方,并将结果除以负无穷大。

如果您想模拟负值的无符号右移(在java和javascript中可用),则必须使用所考虑的固定位数将负值转换为正数。将给出预期价值的权利转移:

代码语言:javascript
复制
x = -1
x32 = x & 0xffffffff   # convert to 32-bit unsigned value
x >> 8                 # produces -1
x32 >> 8               # produces 0x00ffffff
票数 6
EN

Stack Overflow用户

发布于 2021-01-26 19:36:39

我认为你的问题的答案取决于你是如何储存你的数字。如果希望0b11000101表示-59,则需要在执行移位之前以某种方式指定位长。请注意,Python对否定的二进制表示不是以2的补语格式表示的:

代码语言:javascript
复制
>>> bin(59)
'0b111011'
>>> bin(-59)
'-0b111011'

因此,如果-0b111011适用于您的目的,那么您可以执行chqrlie的答案中指定的算术右移。

但是,如果您需要您的结果以2的补码格式表示,即需要将0b11000101算术右移2来计算为字面上的0b11110001,那么下面的函数应该适用于您:

代码语言:javascript
复制
# x is an n-bit number to be shifted m times
def sra(x,n,m):
    if x & 2**(n-1) != 0:  # MSB is 1, i.e. x is negative
        filler = int('1'*m + '0'*(n-m),2)
        x = (x >> m) | filler  # fill in 0's with 1's
        return x
    else:
        return x >> m

这基本上是执行规则的右移,但如果数字是负数(2的补码格式,具有指定的位长),则用1填充前导零。

示例:

代码语言:javascript
复制
sra(0b11000101, 8,  2)    -> 0b11110001
sra(0x805a6cf3, 32, 0x10) -> 0xffff805a
sra(0x705a6cf3, 32, 0x10) -> 0x0000705a
票数 0
EN

Stack Overflow用户

发布于 2020-11-23 08:07:55

不是python编码器,但我通常这样解决这个问题:

代码语言:javascript
复制
x = (x>>1)|(x&80);        //  8bit
x = (x>>1)|(x&8000);      // 16bit
x = (x>>1)|(x&80000000);  // 32bit

因此,只需将原始MSb的x复制到由位移位创建的空间中即可。然而,这将只适用于轮班1位。为了获得更多信息,您需要这样做:

代码语言:javascript
复制
if (x<0) x = (x>>2)|0xC0;       else x = x>>2; //  8bit
if (x<0) x = (x>>2)|0xC000;     else x = x>>2; // 16bit
if (x<0) x = (x>>2)|0xC0000000; else x = x>>2; // 32bit

if (x<0) x = (x>>3)|0xE0;       else x = x>>3; //  8bit
if (x<0) x = (x>>3)|0xE000;     else x = x>>3; // 16bit
if (x<0) x = (x>>3)|0xE0000000; else x = x>>3; // 32bit

if (x<0) x = (x>>4)|0xF0;       else x = x>>4; //  8bit
if (x<0) x = (x>>4)|0xF000;     else x = x>>4; // 16bit
if (x<0) x = (x>>4)|0xF0000000; else x = x>>4; // 32bit

if (x<0) x = (x>>5)|0xF8;       else x = x>>5; //  8bit
if (x<0) x = (x>>5)|0xF800;     else x = x>>5; // 16bit
if (x<0) x = (x>>5)|0xF8000000; else x = x>>5; // 32bit

...

您可以为掩码创建LUT。

代码语言:javascript
复制
LUT8[8]=
    {
    0x00, 
    0x80, 
    0xC0, 
    0xE0, 
    0xF0, 
    0xF8, 
    0xFC, 
    0xFE, 
    }

if (x<0) x = (x>>k)|LUT8[k&7]; else x = x>>k; //  8bit

k位移位的掩码仅仅是包含来自MSb的k 1的数字,其余的是二进制的零。

还有更简单的解决方案(代价是两次否定),如下所示:

代码语言:javascript
复制
if (x<0) x = -((-x)>>k); else x = x>>k;
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64963170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档