一.算数移位
1.原码的算数移位一一符号位保持不变,仅对数值位进行移位
算数移位是通过改变各个数码位和小数点的相对位置,从而改变各数码位的位权。可用移位运算实现乘法,除法。例如:
1(符号位), 0001010.0= + =-10D
将算数右移(右移后低位舍弃,高位补0):
1, 00101.00--->1,0000101=+=-5D,也就是-10D/2
我们再继续右移
1, 0000010.1--->1,0000010(低位被舍弃)= -2D,这不是-5D的一半
因为舍去了低位的1,这个1代表,所以若舍弃的位=0,则相当于2,若舍弃的位就会丢失精度
同理:
1,0101000=-40D
经过左移得到
1,1010000=-80D
再次左移
1,0100000=-32D,而不是-160D,这是因为7位bit位只能表示0~127的绝对值的范围,这个值已经超出了范围,这样就会出现严重误差。
右移:高位补0,低位舍弃。若舍弃的位=0,则相当于2;若舍弃的位,则会丢失精度
左移:低位补0,高位舍弃。若舍弃的位=0,则相当于X2;若舍弃的位,则会出现严重误差
2.反码的算数移位
正数:
正数的反码与原码相同,因此对正数反码的移位运算也和原码相同。即右移:高位补0,低位舍弃。左移:低位补0,高位舍弃。
负数:
负数的反码数值位与原码相反,因此负数反码的移位运算规则如下:
右移:高位补1,低位舍弃
左移:低位补1,高位舍弃
3.补码的算数移位
正数:
正数的补码与原码相同,因此对正数补码的移位运算也和原码相同。即右移:高位补0,低位舍弃。左移:低位补0,高位舍弃。
负数:
根据补码的规律,最右边的“1”的右边的数与原码一致,左边的数与反码相同,不太熟悉可以看看:
所以补码的负数的算数移位规则如下:
右移(同反码):高位补1,低位舍弃。
左移(同原码):低位补0,高位舍弃。
总结:
举例:如果想实现-20*7的效果,那么计算机就将不左移,左移1位,左移两位的数进行相加,完成乘法操作。
二.逻辑移位
右移:高位补0,低位舍弃。
左移:低位补0,高位舍弃。
可以把逻辑移位看作是对"无符号数"的算数移位。
例如获取RGB值的过程:
R=102 01100110
G=139 10001011
B=139 10001011
三.循环移位
循环左移后移出的数会被补到最右边
右移同理,循环右移后,右边移出的数会被补到最左边
带进位位的循环移位:
循环左移会将原本数值的最高位,移动到进位位CF,并且将原本CF的值,补到最右边
循环右移同理,将数值位的最低位放到CF中,CF的值放到数值位的最高位中
循环移位一般用在大端存储和小端存储转换中,大端存储和小端存储的含义如下:
大端是高字节存放到内存的低地址
小端是高字节存放到内存的高地址
以32位int型数0x12345678举例:
循环移位对于16位bit(2个字节)数的大端小端转换中比较有用,直接向左移动8位bit或向右移动8bit即可。
而对于32位bit可以进行如下处理:
1.将整数表示为4个字节,即[0x12, 0x34, 0x56, 0x78]。
2.将这4个字节的位置进行互换,即将第一个字节和最后一个字节交换,将第二个字节和倒数第二个字节交换。
3.调换后的结果为[0x78, 0x56, 0x34, 0x12]。