移位运算分为算术移位、逻辑移位、循环移位
在算术移位中,通过改变数码位和小数点的相对位置,从而实现各个数码位的位权。
在各机器码的移位中,左移相当于 ×2
,右移相当于 ÷2
,但由于位数有限,会造成溢出,就无法精确的等效乘除法。
原码的算术移位,符号位不参与移位,由于小数点是相对固定的,所以将数码位进行左右移动
- 左移,高位舍弃,低位补
0
- 如果舍弃的是
1
,会出现严重误差 - 如果舍弃的是
0
,相当于×2
- 如果舍弃的是
- 右移,低位舍弃,高位补
0
- 如果舍弃的是
1
,会出现精度问题 - 如果舍弃的是
0
,相当于÷2
- 如果舍弃的是
例:
舍弃的是 0
00101010
对应十进制为42
- 左移一位
01010100
对应十进制为84
- 右移一位
00010101
对应十进制为21
- 左移一位
舍弃的是 1
01010101
对应十进制为85
- 左移一位
00101010
对应十进制为42
- 如果机器位数够,不用舍弃,我们来看下它移位后的值
010101010
对应十进制为170
170
和42
两个值的误差太大了
- 如果机器位数够,不用舍弃,我们来看下它移位后的值
- 右移一位
00101010
对应十进制为42
- 不用舍弃,看下移位后的值
00101010.1
对应十进制为42.5
42.5
和42
两个值只是精度误差
- 不用舍弃,看下移位后的值
- 左移一位
反码的算术移位
- 正数的反码算术移位和原码一样
- 负数的反码算术移位
- 左移,高位舍弃,低位补
1
- 右移,低位舍弃,高位补
1
- 左移,高位舍弃,低位补
例:
- 正数原码
00101010
对应十进制为42
- 反码
00101010
- 左移一位
01010100
- 右移一位
00010101
- 左移一位
- 反码
- 负数原码
10101010
对应十进制为-42
- 反码
11010101
- 左移一位
10101011
- 右移一位
11101010
- 左移一位
- 反码
为啥负数的反码在移位时是补 1
呢?
因为负数的反码是在原码的基础上取反,所以为了保证数值上的统一,原码移位时是补 0
,那反码就补 1
补码的算术移位
- 正数的补码算术移位和原码相同
- 负数的补码算术右移
- 负数补码左移(同原码):低位补
0
,高位舍弃 - 负数补码右移(同反码):高位补
1
,低位舍弃
- 负数补码左移(同原码):低位补
例:
- 正数原码
00101010
,对应十进制为42
- 补码
00101010
,- 左移一位:
01010100
- 右移一位:
00010101
- 左移一位:
- 补码
- 负数原码
10101010
,对应十进制为-42
- 补码
11010100
- 左移一位:
10101000
- 右移一位:
11101010
- 左移一位:
- 补码
为啥负数补码移位会分情况呢?
可以从负数原码、反码、补码他们之间找规律,比如 -42
:
- 原码:
10101010
- 反码:
11010101
- 补码:
11010110
从右边开始数到第一个 1
的地方,1
(包括 1
)的右边同原码一样,左边同反码一样
- 左移,右边同原码一样,在右边(低位)补
0
- 右移,左边同反码一样,在左边(高位)补
1
码制 | 补代码 | |
---|---|---|
正数 | 原码、反码、补码 | 0 |
负数 | 原码 | 0 |
负数 | 反码 | 1 |
负数 | 补码 | 左移补0 |
负数 | 补码 | 右移补1 |
逻辑移位:可以看作是对“无符号数”的算术移位
- 右移:高位补 0,低位舍弃
- 左移:低位补 0,高位舍弃
循环移位分为不带进位位和带进位位两种: