尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

原码反码补码移码详解:从模运算到溢出判断一网打尽

原码反码补码移码详解:从模运算到溢出判断一网打尽 这次我们直接把这四个数制放到同一张表里对比原码、反码、补码、移码。它们不是四个孤立的概念而是同一条二进制规则链上的四个环节。只要理解了“模运算”和“符号位参与运算”这两件事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)补码符号位取反真值加偏置值浮点阶码、比较大小有几个结论必须刻进脑子补码比原码、反码多表示一个最负数例如 8 位补码能表示 -128而原码、反码只能到 -127。补码的 0 只有一种编码全是 0原码和反码都有正零、负零两种编码。移码的 0 也只有一种编码且移码的最小编码全 0 对应最小的负数。补码加减运算时符号位参与运算最终结果自动得到补码形式不需要额外处理符号位。移码比较大小直接按无符号数比较即可这是移码设计的目的之一。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 01010 的原码是 0000 0000-0 的原码是 1000 0000原码的问题很明显符号位不能直接参与运算做加减法需要先判断符号逻辑复杂而且有两个 0。4.2 反码反码的规定正数的反码等于原码。负数的反码是符号位不变数值位按位取反。所以5 的反码是 0000 0101-5 的反码是 1111 10100 的反码是 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)-1127k 是阶码位数。这是考试中最容易丢分的地方之一。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 0101y 3[y]补 0000 0011[-y]补 1111 1101[5 - 3]补 0000 0101 1111 1101 0000 0010最高位进位丢弃结果是 2正确。运算时所有位都参与加法符号位产生的进位直接丢弃不需要额外处理。5.2 什么情况会溢出补码加减法溢出发生在“运算结果超出表示范围”时。以 4 位补码为例范围是 -8 ~ 7。两个正数相加结果超过 7就是上溢。例如 5 4 99 超过 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 的补码001115 的补码00101第二步相加00111 00101 ------- 01100第三步结果 01100最高位是 0说明符号位是正但数值位是 1100即 12。检查一下范围5 位补码范围是 -16 ~ 157 5 12没有超出范围。但用双符号位看7 的双符号位补码0001115 的双符号位补码000101相加得到 001100两个符号位都是 0没有溢出。再看 7 97 的补码001119 的补码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按补码-14 位二进制串 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 125125 的二进制是 0111 1101。解法二-3 的补码是 1111 1101符号位取反得到 0111 1101。两种方法结果一致。再看本题的变体偏置值为 127求 -3 的移码。此时不能直接符号位取反要按定义计算-3 127 124124 的二进制是 0111 1100。如果题目问“IEEE 754 单精度浮点数的阶码”那就是 8 位、偏置 127。这是最容易被惯性思维坑的地方。7.3 移码加减法的注意事项移码有两个很隐蔽的性质移码本身不能直接做加减法。两个移码相加后结果并不是真实结果的移码而是多了一个偏置值。例如真值 5 和 35 的移码 1000 01013 的移码 1000 0011相加得到 1 0000 1000符号位进位丢弃后是 0000 1000即 8。而 5388 的移码是 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 115115 的二进制是 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 ------- 1101115 位结果保留低 5 位10111。10111 是补码符号位为 1是负数。数值位取反加 101000 1 01001即 9所以真值是 -9。-6 - 3 -95 位补码范围是 -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 做题顺序建议第一次接触这个知识点时建议按固定流程处理每一道题看题目标示的字长确定 n 的数值。判断题目要求的是原码、反码、补码还是移码。如果是补码运算先写全补码而不是先写原码再心算。运算时把符号位当作数值位参与加法。算完后用双符号位法或进位比较法检查是否溢出。如果题目涉及浮点阶码确认偏置值是 2^(n-1) 还是 2^(n-1)-1。这套流程看起来繁琐但能避免绝大多数低级错误。10.2 一个建议把所有特殊值写一遍把 8 位的几个特殊值背熟能大幅提高计算速度真值原码反码补码移码偏置1281270111 11110111 11110111 11111111 111110000 00010000 00010000 00011000 000100000 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. 结语原码、反码、补码、移码这一块难的不是概念本身而是运算中容易丢分的小细节。考试只要抓住三件事第一补码的最高位是符号位但符号位要参与运算溢出靠双符号位判断。第二移码是“真值加偏置值”比较大小直接按无符号数看做加减法必须修正偏置值。第三同一个二进制串在不同解释方式下代表不同的值无符号数和补码不能混用。把这三点落实到位再配合几道完整例题练习这套考法基本能稳定拿下。建议把这篇文章中的表格截图保存复习时先看表再做题效率会比反复刷网课更高。
返回列表