3.2 原码、补码、反码
内容导视:
- 使用二进制表示正负数
- 1 个字节表示 -128 ~ 127
- 猜测为什么计算机要以补码形式存储
3.2.1 使用二进制表示正负数
采用最高位是符号位的方法来区分正负数,正数的符号位为 0、负数的符号位为 1。
原码是带符号位的二进制码。用 8 位(1 个字节)表示一个整数,3 的原码为 00000011
,-3 的原码为 10000011
。
其实计算机存储数据时,一律储存二进制的补码形式。
对于正整数来说,原码、反码、补码相同。
对于负整数来说,反码的符号位不变,其它位取反(1、0 互换);补码是反码 + 1。
例 1:-1 的补码
原码:10000001
反码:符号位不变,其它位取反,11111110
补码:反码 + 1,11111111
所以 -1 的补码是 11111111
例 2:补码 10000010 对应的十进制整数
通过符号位可以看出是负数的补码,因为正数三码相同,不可能符号位为 1
补码:10000010
反码:补码 - 1,10000001
原码:11111110
原码 1111110 对应的十进制为 254
再加上符号位 1,原码 11111110 对应 -254
所以补码 10000010 对应的十进制整数为 -254
3.2.2 1 个字节表示 -128 ~ 127
要表示的十进制数 | 原码 | 反码 | 补码 |
---|---|---|---|
+0 | 00000000 | 00000000 | 00000000 |
1 | 00000001 | 00000001 | 00000001 |
2 | 00000010 | 00000010 | 00000010 |
3 | 00000011 | 00000011 | 00000011 |
4 | 00000100 | 00000100 | 00000100 |
… | |||
126 | 01111110 | 01111110 | 01111110 |
127 | 01111111 | 01111111 | 01111111 |
到 128 时,原码:10000000,错误,因为最高位是符号位,这会被误以为是负数,所以 128 超出了 1 个字节能够表示的范围。
要表示的十进制数 | 原码 | 反码 | 补码 |
---|---|---|---|
-0 | 10000000 | 11111111 | 00000000 |
-1 | 10000001 | 11111110 | 11111111 |
-2 | 10000010 | 11111101 | 11111110 |
-3 | 10000011 | 11111100 | 11111101 |
-4 | 10000100 | 11111011 | 11111100 |
… | |||
-126 | 01111110 | 10000001 | 10000010 |
-127 | 11111111 | 10000000 | 10000001 |
若超出 8 位,就截去前面的多余位数。如 100000000 是 9 位,截去前面一位为 00000000。
1 个字节 8 位,最多表示 28 = 256 个数,以原码的形式存储数据时,由于 0 的表示方法有两种:00000000、10000000,浪费了一种表示方法,实际表示的数的范围:[-127,127] 一共 255 个。
如果以补码的形式存储数据,0 的表示方法统一了,都是 00000000,还有补码 10000000 未被使用,用于表示 -128,实际表示的数的范围:[-128,127]。
3.2.3 猜测为什么计算机要以补码形式存储
除了以补码形式存储可以多存一个数的原因,方便减法运算转为加法运算也是一个关键的因素吧。
二进制加法:0 + 0 = 0,0 + 1 = 1,1 + 1 = 0 进 1 位。
例 1:1 - 1 = ?
1 - 1 = 1 + (-1)
1 的补码为:00000001,-1 的补码为 11111111,0 的补码 00000000
以补码形式做加法,得到的补码,再转为整数
00000001
+ 11111111
= 00000000
00000000 是 0 的补码,所以运算结果为 0
例 2:24 - 4 = ?
24 - 4 = 24 + (-4)
24 的补码为:00011000,-4 的补码为 11111100
00011000
+ 11111100
= 00010100
00010100 是正数的补码、反码、原码,转为十进制为 20
使用补码,运算变得更方便。