原码反码补码移码详解:从模运算到溢出判断一网打尽
2026/8/31 10:36:46 网站建设 项目流程

这次我们直接把这四个数制放到同一张表里对比:原码、反码、补码、移码。它们不是四个孤立的概念,而是同一条二进制规则链上的四个环节。只要理解了“模运算”和“符号位参与运算”这两件事,408 计组里大部分关于补码加减、溢出判断、移码比较大小的题目都能稳定得分。

这篇文章会按“定义 → 转换 → 加减运算 → 溢出判断 → 移码考点 → 经典例题”的顺序展开。先说清楚每个码制的数学本质,再直接进入考法,最后给出全套易错点清单。适合正在复习 408 计算机组成原理、准备期末考,或者面试前快速过一遍数据表示与运算基础的人。

1. 核心考点速览

先给一张总表,把四种码制的关键属性一次性说清。这张表建议直接收藏,做题前先对着它捋一遍思路。

码制符号位数值位0 的表示表示范围(n位定点整数)与真值的转换方式常考位置
原码最高位,0正1负真值绝对值+0 和 -0 两种-(2^(n-1)-1) ~ +(2^(n-1)-1)符号位不变,数值位直接读绝对值概念辨析、溢出边界
反码最高位,0正1负正数同原码,负数按位取反+0 和 -0 两种-(2^(n-1)-1) ~ +(2^(n-1)-1)负数数值位取反过渡概念,用于推导补码
补码最高位,0正1负负数反码+1只有一种,全0-2^(n-1) ~ +(2^(n-1)-1)负数连同符号位取反加1加减运算、溢出判断
移码与补码符号位相反同补码数值位只有一种-2^(n-1) ~ +(2^(n-1)-1)补码符号位取反;真值加偏置值浮点阶码、比较大小

有几个结论必须刻进脑子:

  1. 补码比原码、反码多表示一个最负数,例如 8 位补码能表示 -128,而原码、反码只能到 -127。
  2. 补码的 0 只有一种编码,全是 0;原码和反码都有正零、负零两种编码。
  3. 移码的 0 也只有一种编码,且移码的最小编码全 0 对应最小的负数。
  4. 补码加减运算时,符号位参与运算,最终结果自动得到补码形式,不需要额外处理符号位。
  5. 移码比较大小,直接按无符号数比较即可,这是移码设计的目的之一。

2. 适用学习人群与复习边界

2.1 适合谁看

这套知识点覆盖的人群很宽:

  • 408 考研党:计算机组成原理第二章“数据的表示与运算”,几乎每年都会涉及原码、反码、补码、移码中的 1 到 2 题。补码加减和溢出判断是简答题、选择题的高频方向。
  • 计算机专业期末考生:不管是“计算机组成原理”还是“数字逻辑”,数制转换和补码运算都是基础题。
  • 面试准备者:C/C++ 面试里 int 溢出、unsigned 比较、负数右移等题目,本质就是补码和无符号数的区别。
  • 写底层代码的开发者:做嵌入式、通信协议、音视频编解码时,经常要手动处理二进制位、字节序和定点数。

2.2 复习边界

这篇文章解决的是“码制转换 + 补码运算 + 移码比较”这三大块。像浮点数完整规格化、乘除运算器结构、CRC 校验这些内容,本文只会在涉及移码偏置值时提及,不会展开。

换句话说,看完本文你能稳定解决的是:给定一个真值写四种码制、给定补码求真值、补码加减法并判断溢出、移码与补码互转、浮点阶码中移码比较大小。这些都是应试中性价比最高的部分。

3. 前置知识:模运算与机器字长

3.1 模运算的思想

补码的核心是模运算。简单说,一个 n 位二进制计数器,从 0 开始不断加 1,加到全 1 后再加 1,会回到全 0。这个“溢出丢弃”的过程,就是自动取模。

n 位无符号数的模是 2^n。例如 4 位无符号数范围是 0~15,计数器溢出后回到 0,相当于对 16 取模。

补码就是利用这个溢出特性,把减法转换成加法:

x - y = x + y 的补数(对模 2^n 而言)

一个数的补数就是等于 2^n - 这个数。对二进制来说,“取反加一”就是求补数的快捷方式。这就是为什么补码叫“补”码:它补的是模。

3.2 机器字长是什么

机器字长就是一次能处理的二进制位数,常见的是 8、16、32、64。字长决定了:

  • 无符号数表示范围:0 ~ 2^n - 1
  • 补码表示范围:-2^(n-1) ~ 2^(n-1) - 1
  • 原码、反码表示范围:-(2^(n-1)-1) ~ 2^(n-1) - 1

做题时第一件事永远是确认字长。字长不同,同一个二进制串代表的真值完全不同。

4. 四种码制的定义与互相转换

4.1 原码

原码是最直观的表示法:最高位是符号位,剩余位是数值的绝对值。

以 8 位为例:

  • +5 的原码是 0000 0101
  • -5 的原码是 1000 0101
  • +0 的原码是 0000 0000
  • -0 的原码是 1000 0000

原码的问题很明显:符号位不能直接参与运算,做加减法需要先判断符号,逻辑复杂,而且有两个 0。

4.2 反码

反码的规定:

  • 正数的反码等于原码。
  • 负数的反码是符号位不变,数值位按位取反。

所以:

  • +5 的反码是 0000 0101
  • -5 的反码是 1111 1010
  • +0 的反码是 0000 0000
  • -0 的反码是 1111 1111

反码本身不常用于直接运算,但在推导补码时是必经路径。

4.3 补码

补码的规定:

  • 正数的补码等于原码。
  • 负数的补码是反码加 1。

所以:

  • +5 的补码是 0000 0101
  • -5 的补码是 1111 1011

补码统一了加法和减法,符号位可以直接参与运算。这是计算机中整数默认用补码存储的根本原因。

4.4 移码

移码的定义:

移码 = 真值 + 偏置值

最常见的偏置值是 2^(n-1),也就是把整个取值范围往正方向平移,让最小负数变成全 0。

n 位移码的取值范围正好是 0 ~ 2^n - 1,因此可以直接按无符号数比较大小,这也是移码用于浮点阶码的原因。

8 位二进制,偏置值为 128:

  • 真值 +5 的移码 = 5 + 128 = 133 = 1000 0101
  • 真值 -5 的移码 = -5 + 128 = 123 = 0111 1011
  • 真值 -128 的移码 = -128 + 128 = 0 = 0000 0000

注意,这里使用的偏置值是 2^(n-1)=128。IEEE 754 浮点数的阶码也使用移码,但偏置值改成 2^(k-1)-1=127,k 是阶码位数。这是考试中最容易丢分的地方之一。

4.5 补码与移码的快速互转

当偏置值是 2^(n-1) 时,补码转移码有一个很实用的结论:

移码 = 补码的符号位取反,数值位不变。

验证:

  • 真值 +5:补码 0000 0101,符号位取反得到 1000 0101,正好是移码。
  • 真值 -5:补码 1111 1011,符号位取反得到 0111 1011,正好是移码。

这个结论可以节省大量计算时间。

但必须注意,这个结论只在偏置值 = 2^(n-1) 时成立。IEEE 754 的偏置值是 2^(k-1)-1,就不能直接符号位取反,需要按真值 + 偏置值重新计算。很多题目在这里设陷阱。

5. 补码加减运算与溢出判断

5.1 补码加减法规则

补码加减法只有两条规则:

  • [x + y]补 = [x]补 + [y]补
  • [x - y]补 = [x]补 + [-y]补

其中 [-y]补 的求法是:把 [y]补 连同符号位一起取反,再加 1。

例如 8 位补码:

  • x = 5,[x]补 = 0000 0101
  • y = 3,[y]补 = 0000 0011
  • [-y]补 = 1111 1101
  • [5 - 3]补 = 0000 0101 + 1111 1101 = 0000 0010(最高位进位丢弃)

结果是 2,正确。

运算时所有位都参与加法,符号位产生的进位直接丢弃,不需要额外处理。

5.2 什么情况会溢出

补码加减法溢出发生在“运算结果超出表示范围”时。以 4 位补码为例,范围是 -8 ~ 7。

两个正数相加,结果超过 7,就是上溢。例如 5 + 4 = 9,9 超过 7,溢出。

两个负数相加,结果小于 -8,就是下溢。例如 -5 + (-4) = -9,-9 小于 -8,溢出。

特别注意:一正一负相加不会溢出,因为结果一定落在两个数的范围内。

5.3 溢出判断的三种方法

第一种:双符号位法,也叫做变形补码。用两个符号位表示正负,00 表示正,11 表示负。加法运算后,如果两个符号位不同,就说明溢出:

  • 01 表示上溢,正数相加溢出。
  • 10 表示下溢,负数相加溢出。
  • 00 或 11 表示没有溢出。

例如 4 位补码加 5 和 4,先用双符号位表示:00101 + 00100 = 01001。两个符号位是 01,上溢。

第二种:单符号位比较进位法。只要最高数值位向符号位的进位,与符号位产生的进位不同,就说明溢出。

第三种:符号位与数值位最高位的进位异或。两个进位不同则溢出。

这三种方法本质一样,考试中推荐使用双符号位法,最直观、不容易错。

5.4 补码加减法完整示例

题目:用 5 位补码计算 7 + 5,并判断是否溢出。

第一步,求补码:

  • 7 的补码:00111
  • 5 的补码:00101

第二步,相加:

00111 + 00101 ------- 01100

第三步,结果 01100,最高位是 0,说明符号位是正,但数值位是 1100,即 12。

检查一下范围:5 位补码范围是 -16 ~ 15,7 + 5 = 12,没有超出范围。

但用双符号位看:

  • 7 的双符号位补码:000111
  • 5 的双符号位补码:000101
  • 相加得到 001100,两个符号位都是 0,没有溢出。

再看 7 + 9:

  • 7 的补码:00111
  • 9 的补码:01001
  • 相加得到 10000

用双符号位:000111 + 001001 = 010000,符号位是 01,上溢。

这里从单符号位角度看,结果是 10000,符号位变成 1,看起来像 -16,但这其实是因为溢出后符号位被覆盖了。所以判断溢出时不能只看最终符号位,必须比较进位。

6. 无符号数与补码的区分

6.1 同一个二进制串,两套解释

无符号数和补码是同一个二进制串的两种解释方式:

  • 无符号数:所有位都是数值位,范围 0 ~ 2^n - 1。
  • 补码:最高位是符号位,范围 -2^(n-1) ~ 2^(n-1) - 1。

4 位二进制串 1111:

  • 按无符号数:15
  • 按补码:-1

4 位二进制串 1000:

  • 按无符号数:8
  • 按补码:-8

这就是“无符号数的补码”这个概念容易混的原因。很多教材里说“无符号数也有补码”,意思是:无符号数本身也可以被解释成补码形式的有符号数,关键看你怎么定义符号位。

6.2 C 语言里的典型陷阱

这段代码是面试常客:

#include <stdio.h> int main() { int x = -1; unsigned int y = 1; if (x < y) { printf("x < y\n"); } else { printf("x >= y\n"); } return 0; }

实际输出是 “x >= y”。

原因:C 语言中,有符号数和无符号数做比较时,有符号数会隐式转换成无符号数。-1 的补码是 0xFFFFFFFF,按无符号数解释就是 4294967295,远大于 1,所以 x >= y。

这种按无符号数解释补码的规则,考试中经常结合“无符号数的补码”出选择题。解题时先明确操作数是有符号还是无符号,再决定解释方式。

7. 移码的经典考法

7.1 移码的本质

移码的真正用途是“让比较大小变得简单”。

浮点数比较大小时,如果阶码直接用补码,比较两个负数会非常麻烦,因为补码的数值越大,真值越小。但移码把所有真值映射到无符号数范围,真值越大,移码越大,直接无符号比较即可。

这就是很多 408 题目中浮点数阶码用移码,尾数用原码或补码的原因。

7.2 移码与补码的转换考法

最常见的直接考法是:

题目:设 8 位机器数采用移码表示,偏置值为 128,求十进制真值 -3 的移码。

解法一:-3 + 128 = 125,125 的二进制是 0111 1101。

解法二:-3 的补码是 1111 1101,符号位取反得到 0111 1101。

两种方法结果一致。

再看本题的变体:偏置值为 127,求 -3 的移码。

此时不能直接符号位取反,要按定义计算:-3 + 127 = 124,124 的二进制是 0111 1100。

如果题目问“IEEE 754 单精度浮点数的阶码”,那就是 8 位、偏置 127。这是最容易被惯性思维坑的地方。

7.3 移码加减法的注意事项

移码有两个很隐蔽的性质:

  • 移码本身不能直接做加减法。两个移码相加后,结果并不是真实结果的移码,而是多了一个偏置值。例如真值 5 和 3,5 的移码 1000 0101,3 的移码 1000 0011,相加得到 1 0000 1000,符号位进位丢弃后是 0000 1000,即 8。而 5+3=8,8 的移码是 1000 1000。结果差了 128。所以移码加减后必须再减一次偏置值。
  • 移码比较大小可以直接按无符号数比较,不需要转换。例如判断 -1 和 -2 的移码,-1 的移码是 127,-2 的移码是 126,所以 -1 > -2,与无符号比较一致。

考试中涉及移码运算时,先问自己:题目让我做的是“比较大小”还是“加减运算”?比较大小用无符号规则,加减运算要修正偏置。

8. 经典例题演练与解析

8.1 例题一:四种码制转换

题目:写出 -13 的 8 位原码、反码、补码、移码(偏置值 128)。

解析:

  • 原码:符号位为 1,数值位是 13 的二进制 0001101,所以是 1000 1101。
  • 反码:符号位不变,数值位取反,得到 1111 0010。
  • 补码:反码加 1,得到 1111 0011。
  • 移码:补码符号位取反,得到 0111 0011。

验证移码:-13 + 128 = 115,115 的二进制是 0111 0011,一致。

这道题的易错点在反码。取反时只对数值位取反,符号位保持不变。如果连符号位一起取反,反码就变成了 0111 0010,但这其实是补码符号位取反后的样子,恰好等于移码的数值位,容易混淆。

8.2 例题二:补码求真值

题目:8 位补码 1110 1000 对应的十进制真值是多少?

解析:

方法一:按负数处理。补码减 1 得到反码 1110 0111,再按位取反得到 1001 1000。数值位 0011000 是 24,符号位为 1,所以真值是 -24。

方法二:直接按公式。这是最推荐的做法:原码数值位 = 补码数值位取反加 1。1110 1000 数值位 110 1000 取反得到 001 0111,加 1 得到 001 1000,即 24,符号位为 1,所以是 -24。

还有一种更快的做法:把补码看成“全 1 补码表示 -1”,然后用差值法。1110 1000 与全 1 的 1111 1111 相差 0000 0111,即 7。全 1 表示 -1,所以 1110 1000 表示 -1 - 7 = -8。但这里 1110 1000 实际是 -24,差值与 -1 之间不是这个关系,这种方法不通用。最稳妥的还是取反加一。

8.3 例题三:补码减法与溢出

题目:用 5 位补码计算 -6 - 3,并判断是否溢出。

解析:

  • -6 的补码:11010
  • -3 的补码:11101
  • -6 - 3 = -6 + (-3)

加法:

11010 + 11101 ------- 110111

5 位结果保留低 5 位:10111。

10111 是补码,符号位为 1,是负数。数值位取反加 1:01000 + 1 = 01001,即 9,所以真值是 -9。

-6 - 3 = -9,5 位补码范围是 -16 ~ 15,-9 在范围内,不溢出。

用双符号位验证:

  • -6 的双符号位补码:111010
  • -3 的双符号位补码:111101
  • 相加得到 1110111,保留低 6 位,两个符号位都是 11,不溢出。

正确。

8.4 例题四:无符号数陷阱

题目:4 位机器数 1100,按无符号数解释是多少?按补码解释是多少?

解析:

  • 无符号数:8 + 4 = 12。
  • 补码:符号位为 1,是负数。数值位 100 取反加 1,得到 011 + 1 = 100,即 4,所以真值是 -4。

同一个二进制串,按无符号数是 12,按补码是 -4。这种“解释方式决定值”的题目,是 408 选择题常见的送分题,也是 C 语言隐式转换的考点来源。

9. 常见错误与纠错方法

错误现象可能原因纠错方法
负数的原码和补码写反混淆原码与补码的转换步骤记住“负数的补码 = 反码 + 1”,而不是“原码取反加 1”
反码取反时把符号位也取反误以为所有位都取反反码、补码转换时符号位保持不变
补码 1000 0000 写成不能表示只记住范围,没记住补码的唯一最负数8 位补码可表示 -128,原码、反码不行
移码直接用补码符号位取反未确认偏置值是否为 2^(n-1)先看题目的偏置值,IEEE 754 偏置是 127
补码加法出现高位进位就直接判溢出混淆“进位”与“溢出”溢出判断要看符号位进位与最高位进位是否一致
无符号数和补码混用忽略解释方式先统一解释成同一类数再比较
移码加法结果不对忽略偏置值修正两个移码相加后再减一次偏置值;比较大小不用修正
双符号位写下溢写成 01符号位顺序记反01 表示上溢,10 表示下溢,按高位到低位读

10. 复习策略与答题规范

10.1 做题顺序建议

第一次接触这个知识点时,建议按固定流程处理每一道题:

  1. 看题目标示的字长,确定 n 的数值。
  2. 判断题目要求的是原码、反码、补码还是移码。
  3. 如果是补码运算,先写全补码,而不是先写原码再心算。
  4. 运算时把符号位当作数值位参与加法。
  5. 算完后用双符号位法或进位比较法检查是否溢出。
  6. 如果题目涉及浮点阶码,确认偏置值是 2^(n-1) 还是 2^(n-1)-1。

这套流程看起来繁琐,但能避免绝大多数低级错误。

10.2 一个建议:把所有特殊值写一遍

把 8 位的几个特殊值背熟,能大幅提高计算速度:

真值原码反码补码移码(偏置128)
+1270111 11110111 11110111 11111111 1111
+10000 00010000 00010000 00011000 0001
+00000 0000 / 1000 00000000 0000 / 1111 11110000 00001000 0000
-01000 00001111 11110000 00001000 0000
-11000 00011111 11101111 11110111 1111
-1271111 11111000 00001000 00010000 0001
-128无法表示无法表示1000 00000000 0000

这张表有三个观察点:

  • 补码 -128 是唯一一个原码、反码无法表示的特殊值。
  • 移码全 0 是 -128,不是 -0。
  • 原码和反码都有两个 0,补码和移码都只有一个 0。

如果做题时发现某个值落在“无法表示”的区间,说明题目可能故意让你判断可表示范围。

11. 结语

原码、反码、补码、移码这一块,难的不是概念本身,而是运算中容易丢分的小细节。考试只要抓住三件事:

第一,补码的最高位是符号位,但符号位要参与运算,溢出靠双符号位判断。

第二,移码是“真值加偏置值”,比较大小直接按无符号数看,做加减法必须修正偏置值。

第三,同一个二进制串在不同解释方式下代表不同的值,无符号数和补码不能混用。

把这三点落实到位,再配合几道完整例题练习,这套考法基本能稳定拿下。建议把这篇文章中的表格截图保存,复习时先看表,再做题,效率会比反复刷网课更高。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询