nur*_*bha 9 python math bit-shift shift bitwise-operators
某些语言(例如 Java、Verilog)同时具有按位逻辑运算符(<<、>>)和算术移位运算符(<<<、>>>)。
对于无符号值,逻辑移位和算术移位具有相同的操作。假设 8'b11000101 是 8 位无符号数 197 的二进制表示,那么
8'b11000101 >> 2 => 8'b00110001
8'b11000101 >>> 2 => 8'b00110001
8'b11000101 << 2 => 8'b00010100
8'b11000101 <<< 2 => 8'b00010100
Run Code Online (Sandbox Code Playgroud)
对于有符号值,只有算术和逻辑左移操作是相同的,但算术右移会导致符号扩展。假设 8'b11000101 是 8 位有符号数 -59 的二进制表示,那么
8'b11000101 >> 2 => 8'b00110001
8'b11000101 >>> 2 => 8'b11110001
8'b11000101 << 2 => 8'b00010100
8'b11000101 <<< 2 => 8'b00010100
Run Code Online (Sandbox Code Playgroud)
Python只有逻辑移位运算符,没有算术移位运算符。那么如何在Python中实现有符号和无符号值的算术右移呢?
chq*_*lie 10
Python只有逻辑移位运算符,没有算术移位运算符。那么如何在Python中实现有符号和无符号值的算术右移呢?
Python 实际上只有算术移位运算符:
n与乘以 2 次方完全相同。nn取决于被移动的值是否为负。正值除以 2 的幂并向n0 舍入,而负值的行为就像1在最高有效位一侧延伸无限的位串,这是负数的二进制补码表示形式的副作用。这转化为一个单一的数学等价:将整数右移一个正整数,n计算结果为除以 2 次方n并将结果向负无穷大舍入,Math.floor(value / 2**n)如果要模拟负值的无符号右移(如 java 和 javascript 中所示),则必须将负值转换为具有您正在考虑的固定位数的正值。右移将给出期望值:
x = -1
x32 = x & 0xffffffff # convert to 32-bit unsigned value
x >> 8 # produces -1
x32 >> 8 # produces 0x00ffffff
Run Code Online (Sandbox Code Playgroud)
Spe*_*tre -1
不是Python编码员,但我通常会这样解决这个问题:
x = (x>>1)|(x&80); // 8bit
x = (x>>1)|(x&8000); // 16bit
x = (x>>1)|(x&80000000); // 32bit
Run Code Online (Sandbox Code Playgroud)
因此,只需将原始的 MSb 复制x到位移创建的空间中即可。然而,这仅适用于移位 1 位。对于更多你需要做这样的事情:
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
...
Run Code Online (Sandbox Code Playgroud)
您可以为蒙版创建 LUT
LUT8[8]=
{
0x00,
0x80,
0xC0,
0xE0,
0xF0,
0xF8,
0xFC,
0xFE,
}
if (x<0) x = (x>>k)|LUT8[k&7]; else x = x>>k; // 8bit
Run Code Online (Sandbox Code Playgroud)
按位移位的掩码k只是包含k来自 MSb 的数字,然后其余的都是二进制的零。
还有更简单的解决方案(以两次否定为代价),如下所示:
if (x<0) x = -((-x)>>k); else x = x>>k;
Run Code Online (Sandbox Code Playgroud)