原码、反码、补码

原码、反码、补码

原码

1
2
3
1   => 00000001
1 => 00000010
-1 => 10000001

当一个正数与一个负数的原码做加法时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1 + (-1)
00000001
+ 10000001
-----------
10000010

10000010 => -2 // 按原码的方式转化为十进制

2 + (-1)
00000010
+ 10000001
-----------
10000011

10000011 => -3 // 按原码的方式转化为十进制

异号数字的原码相加,原码的符号位一定为1,和实际情况不服,比如: 2 + -1。

反码

1
2
3
4
5
6
// 正数 1
00000001 //原码
00000001 //反码
// 负数 -1
10000001 //原码
11111110 //反码

正数的反码就是原码本身,负数的反码就是原码除符号位外,按位取反。

1
2
3
4
5
6
7
1 + (-1)
00000001 // 1的反码
+ 11111110 // -1的反码
-----------
11111111

11111111 =反码转原码=> 10000000 =转十进制=> -0 // 按原码的方式转化为十进制

反码相加,解决了相反数之间相加的问题,但

1
2
3
4
5
6
7
2 + (-1)
00000010 // 2的反码
+ 11111110 // -1的反码
-----------
00000000

00000000 =反码转原码=> 00000000 =转十进制=> +0 // 按原码的方式转化为十进制

计算结果仍有问题

补码(仍需完善)

正数的补码等于原码,负数的补码等于原码自低位向高位,第一个出现的‘1’及其右边的‘0’保持不变,左边的各位按位取反,符号位不变。

比如在4位系统下:

1
2
3
4
2 + (-1)

0010
+ 1001

将原码计算转换为补码计算:

2 + (-1)=2 + (2^4-1)

二进制编码 十进制 描述
0000 0
0001 1 << 结果位置
0010 2 << 被减数位置
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -8
1001 -1
1010 -2
1011 -3
1100 -4
1101 -5
1110 -6
1111 -7

从上面的表格可以看出,被减数-减数可以看成被减数+减数的同余数,因为在计算机中,最大值溢出后会从0开始重新计数,所以做减法时,可以看成从被减数一直加,加到溢出后,从0开始再加,直到加到结果值位置。累加的总值就是补码的编码(可以理解为补码没有符合位,只是个偏移量),即通过补码=2^n-减数算出补码在十进制的数值,再将补码转成对应的二进制编码。

被减数+补码的值为正数时,因为都是从0累加,所以计算的结果和预期结果值一致,不需要转换。

而当被减数+补码的值为负数时,比如:2 - 4 = -2 => 2 + (16 - 4) = -2=> 2 + 12 = -2

二进制编码 十进制 描述
0000 0
0001 1
0010 2 << 被减数位置
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -8
1001 -1
1010 -2 << 结果位置,记作R2
1011 -3
1100 -4
1101 -5 << R2的反码,记作R3
1110 -6 << 被减数+补码 位置,记作R1
1111 -7
10000(仅用作参考,无符号位,无位数限制) 2^4

2-3=-1 但实际计算出来的编码转化为十进制为-7

2-4=-2 但实际计算出来的编码转化为十进制为-6

可以看出,将预期值的绝对值作为偏移量,实际计算出的二进制值(1110)加上偏移量(0010),刚好等于模(10000)

因为补码+负数的绝对值等于模,且R1+|R2|=模,所以R1R2的补码,所以两数相减为负数时实际计算出来的是结果的补码,要得到原码,需要将补码转换为原码,但1000(补)没有原码,直接就表示原值-2^n

-2可以看成1010=1000+0010(正向偏移),-2的反码可以看成1101=1111-0010(反向偏移)

补码等于反码+1:R3+|R2|+1=模=R1+|R2| => R3+1=R1

类似-2-4这类的,可以看作是(0-2)-4,先算出-2位置的值,再算出-2-4位置的值。

1
2
3
4
5
6
7
8
9
10
11
12
2 + (2^4-1) // 在8位系统下,2^4-1 就是 -1 的补码,负数的绝对值+补码=2^n(n为位数)
0010
+ 1111
----------
0001

2^4-1
1111 // -1的补码

-1
1001 // -1的原码
1110 // -1的反码
分享到