关于「原码、反码、补码」

关于原码反码补码、按位取反、求相反数的计算原理等,一定要熟悉且清晰。

原码、反码、补码

本文例子均为32位int整形变量

基本概念

在计算机中,整数都是以其补码形式进行存储和计算的。

正/负数的补码

首先,原码/反码/补码的最高位为符号位,1代表负数,0代表正数

  • 正数的原码、反码、补码均相同

  • 负数的反码是在原码的基础上,除了符号位不变,其余数值位,逐个取反(~),即为原码的反码

  • 负数的补码是在反码的基础上加1,即为原码的补码

    INT_MIN=0b1000 0000 0000 0000 0000 0000 0000 0000

    反码:0b1111 1111 1111 1111 1111 1111 1111 1111

    补码:0b1000 0000 0000 0000 0000 0000 0000 0000

因此,负数的二进制表示为其 「补码形式」

除了符号位,其余按位取反后,加1即为补码

相反数的补码

注意:符号位也取反,符号 ¬\neg 为按位取反~的意思

①「相反数的反码和 xx 的反码互为相反数」

② 正数的三码相同

③ 负数的补码等于反码加1

xx 是负数

[x]补码=[x]反码=¬x反码=¬(x补码1)[-x]_\text{补码} = [-x]_\text{反码} = \neg x_\text{反码} = \neg (x_\text{补码}-1)

xx 是正数,同理,

[x]补码=[x]反码+1=¬x反码+1=¬x补码+1[-x]_\text{补码} = [-x]_\text{反码}+1=\neg x_\text{反码} + 1 = \neg x_{补码} + 1

其实

无论正数还是负数,其相反数的补码都可以表示为

[x]补码=¬x补码+1[-x]_{补码} = \neg x_{补码} + 1


INT_MIN = 0x8000 0000

1
2
3
4
5
6
7
8
9
10
11
INT_MIN
反码:0b1111 1111 1111 1111 1111 1111 1111 1111
补码:0b1000 0000 0000 0000 0000 0000 0000 0000

-INT_MIN
补码:
0b0111 1111 1111 1111 1111 1111 1111 1111 // 先减1
0b1000 0000 0000 0000 0000 0000 0000 0000 // 所有位取反
原码:
0b1111 1111 1111 1111 1111 1111 1111 1111
0b1000 0000 0000 0000 0000 0000 0000 0000

经过计算发现 -INT_MIN仍然是0x8000 0000,是其本身

使用补码计算

例子1

计算机实际上只会执行加法计算

例如:计算 58558-5时,实际上为58+(5)58+(-5)

1
2
3
4
5
6
7
8
9
58原码 ==>0000 0000 | 0000 0000 | 0000 0000 | 0011 1010

-5原码 ==>1000 0000 | 0000 0000 | 0000 0000 | 0000 0101
-5补码 ==>1111 1111 | 1111 1111 | 1111 1111 | 1111 1010
====>1111 1111 | 1111 1111 | 1111 1111 | 1111 1011
补码相加
==> 0000 0000 | 0000 0000 | 0000 0000 | 0022 0101补码
符号位为0,是正数
结果为 +53,与直观上直接计算58-5结果一致

例子2

任何 intint 变量 xx 减去INT_MIN一定小于0

计算:

58 - INT_MIN

INT_MIN=-2147483648

答案是-2147483590

计算过程如下:

58 + (-INT_MIN)

先转化为补码表示

1
2
3
4
5
6
7
58补码 = 0b0000 0000 0000 0000 0000 0000 0011 1010

INT_MIN补码
0B1111 1111 1111 1111 1111 1111 1111 1111
0b1000 0000 0000 0000 0000 0000 0000 0000 //加1
-INT_MIN补码
0b1000 0000 0000 0000 0000 0000 0000 0000

然后相加,为 0b1000 0000 0000 0000 0000 0000 0011 1010=-2147483590

总结

  • 计算机中,整数都是以其补码形式进行存储和计算

  • 正数的三码相同

  • 负数的反码等于除符号位外按位取反。负数的补码等于反码加1(符号位同样不变)

  • 相反数的反码和 xx 的反码互为相反数。[x]反码=¬x反码[-x]_{反码}=\neg x_{反码}

  • 相反数的补码,等于 xx 补码的每一位按位取反,再加1。即 [x]补码=¬x补码+1[-x]_{补码} = \neg x_{补码} + 1

参考资料


📔博文图谱

提及本博文的链接