资讯动态

原码反码补码移码取值范围详解:推导过程与考点陷阱

发布时间:2026/10/14 4:04:35 来源:尧图企业网站定制
1. 开头为什么取值范围是计算机考研的“送分题”也是“送命题”原码、反码、补码、移码这四种编码方式几乎是计算机组成原理和计算机考研408里必考的基础点。很多同学复习到这一章的时候感觉定义都背下来了正数三种码都一样负数反码按位取反补码在反码基础上加1移码把补码符号位取反。但一做到取值范围的题目就开始出错——8位补码到底能表示到多少定点小数补码为什么能表示-1移码的范围和补码到底是不是一样我在带学生和做技术面试的过程中发现这个考点是典型的“听课全会、做题全废”。原因很简单教材上给的公式往往是一句话带过比如“补码的取值范围比原码多一个最负数”但为什么多多的又是哪个数这个数在二进制里长什么样定点整数和定点小数的结论能否互相套用这些关键推导如果不在脑子里过一遍做题就只能靠死记一换数字就懵。这篇文章就把四种编码方式的取值范围从头到尾推一遍用具体的二进制位串拆解推导过程再把常见的考点陷阱和真题套路整理出来。不管是准备考研、期末考试还是面试刷题这篇都适合作为你复习这个考点时的参考资料。2. 四种编码方式的概念与定位2.1 原码最直观但也是最“浪费”的编码原码的规则很简单最高位是符号位0表示正数1表示负数剩下的位表示数值的绝对值。比如假设字长为8位5的原码是00000101-5的原码是10000101。这种编码方式的优点是符合人的直觉写出来就能看出正负和大小。但它有两个天然的缺陷第一0有正负之分。0是00000000-0是10000000这导致原码能表示的数值个数少了一个也直接影响了它后续做加减法时的硬件设计——直接按位运算结果经常是错的必须先判断符号、比较绝对值再决定谁减谁逻辑非常复杂。第二符号位完全不参与运算。如果你用原码去把正数和负数相加结果不会自动正确。比如01015加上1101-5直接加出来是10010完全不对。所以硬件设计者必须换一种编码方式让符号位也能“自然参与”二进制加法。2.2 反码补码的“过渡形态”反码的规则是正数的反码和原码一样负数的反码是原码除符号位外其余各位按位取反。比如-5的8位原码是10000101反码就是11111010。反码解决了部分符号位参与运算的问题但它继承了一个麻烦0依然有两种表示。0的反码是00000000-0的反码是11111111。也就是说反码和原码一样存在“正零、负零”双编码的问题。其实反码本身在工程中并不直接用于存储和运算它更大的价值是作为推导补码的中间步骤。你可以把反码理解为“为了造出补码而存在的过渡形态”。2.3 补码真正解决加减法问题的方案补码规则正数的补码等于原码负数的补码是反码加1也可以理解成“原码除符号位外取反再加1”。比如-5原码10000101反码11111010补码11111011。补码解决了两个核心问题一是0的编码唯一0和-0的补码都是00000000二是减法可以转化为加法符号位能直接参与运算。比如5加-5写成补码就是00000101加11111011结果是100000000溢出丢弃最高位的1剩下00000000结果正确。这也就是为什么计算机中整数一律用补码存储和运算。你不需要判断符号不需要比较绝对值硬件只需要一个加法器就能完成加减法。2.4 移码专为浮点数阶码设计的偏置编码移码的规则可以简单理解为“补码符号位取反”。比如8位补码表示-5是11111011那-5的移码就是01111011。但这里我不建议你只记“符号位取反”这个操作更推荐把它看成一个数学定义某个数值x的移码等于x加上一个固定的偏置常数。如果字长是n位常见的偏置是(2^{n-1})那么[x]移 (2^{n-1} x)。比如说字长8位偏置就是128那么0的移码就是128二进制为10000000。移码最大的应用场景是浮点数的阶码存储。阶码需要能快速比较大小比如判断两个浮点数谁大谁小本质上要先比较阶码。补码虽然有运算优势但它在比较数值大小时反而不直观——负数补码看起来是个很大的无符号数。移码则让所有真值大小顺序与无符号数大小顺序完全一致这对硬件比较器非常友好。2.5 四种码的对照总结编码方式符号位处理0的编码个数正数表示负数表示原码最高位符号位数值位绝对值2个0和-0与无符号数一致符号位为1数值位取绝对值反码符号位不变数值位取反2个0和-0与原码一致原码数值位取反补码符号位参与运算负数取反加11个与原码一致反码加1移码补码的符号位取反1个补码符号取反补码符号取反这里“0的编码个数”是一个高频考点尤其容易考填空或选择原码和反码的0有两种表示补码和移码的0只有一种表示。3. 定点整数的取值范围推导从“-0”说起的完整逻辑3.1 先约定一个统一的推导框架取值范围题目里最让人混乱的就是“字长到底是多少”。有的题说“8位”有的说“机器字长16位”还有的会说“数值位为n位”。所以我先统一一个框架假设机器字长为n1位其中最高位是符号位剩下n位是数值位。后面凡是推导整数都套这个框架。为什么要设成n1位而不是n位因为符号位和数值位的角色完全不同分开讨论才能把公式写清楚。很多教材说“n位补码的范围是-2^(n-1)到2^(n-1)-1”这里的n指的是总位数。如果你用我的框架把总位数记作m那么数值位就是m-1位公式就要写成-2^(m-1)到2^(m-1)-1。两种写法等价但考试时一定要看清楚题目里的n指的是“总位数”还是“数值位数”这是第一个容易翻车的地方。3.2 原码和反码范围是“对称”的原码的数值位的含义是绝对值的二进制表示。n位数值位的取值范围是000...0到111...1即0到(2^n - 1)。符号位再决定正负。所以正数范围是(0)到(2^n - 1)。负数范围是(-(2^n - 1))到(0)。这里有个细节负数里的0是“-0”。严格来说负数和正数各自都包含了一个0所以整个原码范围是(-(2^n - 1))到((2^n - 1))中间包含两种0的编码。举一个具体例子字长8位符号位1位数值位7位最大正数01111111即127。最小正数非零00000001即1。最大负数绝对值最小10000001即-1。最小负数绝对值最大11111111即-127。还有两种000000000和10000000。所以原码范围是-127到127。反码同理也是-127到127。3.3 补码为什么“多吃”一个数关键在编码全部用上补码和原码最大的区别是原码从“数值绝对值”出发去编码而补码从“模运算”出发去编码。什么是模运算想象一个时钟12点过1小时是1点1点往前1小时是12点。如果规定模是12那么-1在时钟上就等于11。二进制补码的思路完全一样如果字长为8位那么所有运算都在模(2^8256)下进行一个负数x就表示成(256x)。-1的补码(256 (-1) 255)二进制是11111111。 -128的补码(256 (-128) 128)二进制是10000000。所以8位补码能表示的最小数就是-128它的编码是10000000。这个编码在原码眼里是“-0”但在补码体系里“-0”的编码已经被0用掉了因为0的补码只有00000000一个。于是10000000就空出来了补码把它分配给了-128。这就是补码比原码多表示一个最负数的根本原因原码有两个0浪费了一个编码补码只有一个0省出来的编码给了最负数。理论上n位数值位的补码范围是(-2^n)到(2^n - 1)。以字长8位为例n7范围是-128到127。这里我给出一个推导表便于直观理解8位补码的几个关键编码真值8位补码编码12701111111100000001000000000-111111111-12710000001-12810000000你注意看8位补码的所有256个编码从00000000到11111111恰好覆盖了0到255这256个数。如果把它映射到真值顺序是0对应01对应1一直到127对应127然后128对应-128129对应-127依此类推255对应-1。这种映射关系在考试中画一条数轴就能理解配上编码轴更好用。3.4 一个容易被忽略的“循序渐进的边界值记忆法”很多同学在考场上一紧张就忘了-128这个临界值。我平时做题的习惯是走一遍这样的推理链8位补码最大正数先写出来符号位0数值位全1即01111111这是127。最小负数怎么找先想“补码全0之外所有位都是0的情况”11111111是-110000000是最负数需要判断它是多少。因为补码的编码顺序是“从0开始递增对应真值从0到127再从-128递增到-1”所以10000000就是编码128真值为128-256-128。这个逻辑链不依赖记忆只需要根据“模256”的概念推导即可。4. 定点小数的取值范围推导别拿整数的结论直接套4.1 定点小数的约定小数点固定在符号位之后有了整数的基础很多人会天真地想定点小数不就是在整数后面点个小数点嘛范围除以一个倍数就行了。大错特错。定点小数的约定是这样的机器字长还是n1位最高位符号位但小数点约定在符号位和数值位之间。也就是说符号位右边那一位是二进制的(2^{-1})位再右边是(2^{-2})位依此类推最后一位是(2^{-n})位。所以数值位的全部位都表示小数部分没有整数部分。范围推导其实和整数一模一样只是把“2的整数次幂”换成“2的负数次幂”。4.2 原码小数的边界与对称性原码定点小数中最大正数符号位0数值位全1。数值位全1表示的是(\frac{1}{2} \frac{1}{4} ... \frac{1}{2^n})这是个等比数列求和结果是(1 - 2^{-n})。所以最大正数是(1 - 2^{-n})。最小正数是符号位0数值位最右边一位为1即(2^{-n})。负数区间与正数区间对称最小负数是(-(1 - 2^{-n}))最大负数是(-2^{-n})。同时要记住还有0和-0两个特殊编码。以8位字长1位符号位7位数值位为例原码最大正数0.1111111即(1 - 2^{-7} \frac{127}{128})。原码最小正数0.0000001即(2^{-7} \frac{1}{128})。原码最小负数1.1111111即(-\frac{127}{128})。原码最大负数1.0000001即(-\frac{1}{128})。范围总结原码定点小数范围是(-(1 - 2^{-n}))到((1 - 2^{-n}))这一结论与整数保持“对称”的模式一致。4.3 补码小数的特殊点多出-1补码定点小数的正数范围与原码相同(2^{-n})到(1 - 2^{-n})。但在负数方向补码多出了一个最负数也就是-1。-1的补码编码是什么符号位为1数值位全0即1.000...0。为什么它能表示-1还是回到模运算。定点小数的模是2因为小数点后n位满1后进位模为2所以在模2的体系下-1的补码是(2 (-1) 1)二进制就是1.000...0。这个编码在原码里看是“-0”但补码中0的编码只有0.000...0所以1.000...0被解放出来表示-1。因此补码定点小数范围是(-1)到(1 - 2^{-n})。这个“-1能表示1不能表示”的不对称性和“-128能表示128不能表示”的整数情况如出一辙。记住一句话补码的取值范围永远是“负边绝对值比正边大一个最小刻度”。4.4 整数公式与小数公式的统一视角我发现一个好用的记忆视角把整数和小数都看作“以最小刻度为单位”。对定点整数来说最小刻度是1所以8位整数的范围是-128到127跨度是255个刻度加一个0一共256个编码。对定点小数来说最小刻度是(2^{-7})所以8位小数的范围是-1到(1 - 2^{-7})换算成最小刻度就是-128到127个最小刻度一共也是256个编码。所以结论是不管整数还是小数8位补码永远是“-最小刻度×128”到“最小刻度×127”的范围。这个视角能帮你快速判断任何字长的补码范围不只在8位场景下好用。5. 移码范围计算与工程价值5.1 移码的核心定义加偏置才是本质前面简单说过“补码符号位取反”是移码的表面操作。更本质的定义是如果机器字长为n1位1位符号位n位数值位那么移码的真值范围由偏置决定。常用的偏置是(2^n)。此时 [ [x]移 2^n x ]字长8位n7偏置就是128x0移码128二进制10000000。x-128移码0二进制00000000。x-1移码127二进制01111111。x127移码255二进制11111111。所以移码的取值范围和补码一致(-2^n)到(2^n - 1)。以8位为例也是-128到127。5.2 移码为什么适合做浮点阶码浮点数的阶码需要比较大小。比如有两个浮点数指数部分一个是-3一个是5我们需要快速判断后者更大。如果用补码存储阶码-3的补码是11111101。5的补码是00000101。如果把这两个补码直接当无符号数比较11111101明显大于00000101这会导致硬件误判。所以补码不适合直接比较大小。如果用移码存储阶码-3的移码是01111101。5的移码是10000101。还是慢着这里也有点不直观。-3的移码是1255的移码是133125小于133比较结果正确。对任意两个移码只要把它们当作无符号整数比较大小关系都和真值一致。这也是移码偏置为什么设计成(2^n)的原因让最小的真值对应全0编码最大的真值对应全1编码编码顺序和真值大小完全单调对应。硬件里做一个无符号比较器就能完成阶码比较简单粗暴。5.3 移码与补码转换的一个易错点移码和补码的转换虽然只需要把符号位取反但考试里经常在“移码是补码符号位取反”和“移码等于真值加偏置”之间设陷阱。比如题目说“某8位移码偏置值为127”那你不能简单地用补码符号位取反来求移码因为偏置不是128而是127。此时 [ [x]移 127 x ]这个定义在IEEE 754浮点标准里就是典型的偏置设计。所以做题时一定要先看清楚题目给的偏置值是多少再决定用哪种方法。再说一个我遇到很多学生犯的错误有人以为“移码补码符号位取反”是永远成立的。实际上这只是“偏置为(2^n)”时的特例。偏置变了结论就变了。这一点考试中属于区分度比较高的陷阱。5.4 移码与补码的范围对照表编码方式8位整数范围8位小数范围0的编码原码-127到127(-(1-2^{-7}))到(1-2^{-7})2种反码-127到127(-(1-2^{-7}))到(1-2^{-7})2种补码-128到127-1到(1-2^{-7})1种移码偏置128-128到127-1到(1-2^{-7})1种这张表建议抄一遍但不是死背而是背完后再把每一行的推导过程独立推一遍。能推出表才是真掌握。6. 考点陷阱与刷题建议6.1 高频陷阱一题目的“n位”到底含不含符号位最常见的一个翻车点。题目说“某机器字长8位用补码表示定点整数求取值范围”那符号位已经包含在8位里所以数值位是7位范围-128到127。但如果题目改成“某补码的数值位为7位符号位1位”范围还是-128到127。这两种说法结果一样但表述不同。如果题目说“机器字长n位”答案要写成(-2^{n-1})到(2^{n-1}-1)。如果题目说“数值位n位”答案要写成(-2^n)到(2^n-1)。这是最容易丢分的地方每次做题第一件事就是把字长和数值位分清楚。6.2 高频陷阱二0的编码个数原码和反码中有0和-0两个编码补码和移码中只有1个0编码。这个知识点表面简单但会结合“求范围的计数”出现。比如一道题问“8位原码一共能表示多少个不同的数”答案是255个不是256个因为两个编码对应同一个真值0。而8位补码能表示256个不同的数。6.3 高频陷阱三定点小数的范围里没有“整数部分”不少同学推小数范围的时候会把整数的公式直接搬过来写出“8位小数补码范围是-128到127”——这显然是错的。8位定点小数的范围一定在-1到1之间因为它根本没有整数位。做题时先看题目约定的是“定点小数”还是“定点整数”再决定用哪套推导。还有一个迷惑性很强的题如果问“8位补码定点小数能表示的最小负数是多少”很多人会犹豫。答案是-1不是-127/128。解题关键就是想清楚1.0000000代表的是-1而不是-0。6.4 典型例题一给出补码编码求真值题目8位补码序列如下求真值。00000000 → 0。01111111 → 127。10000000 → -128。11111111 → -1。11111011 → 先看它是负数补码。取反加1求原码00000100加1得00000101即5的绝对值所以真值是-5。这类题刷多了之后你会形成条件反射最高位是1直接取反加1转原码再看数值大小。6.5 典型例题二写出范围题目写出16位补码定点整数的取值范围。按前面的推导16位总位数符号位占1位数值位15位。范围是(-2^{15})到(2^{15}-1)即-32768到32767。如果你愿意可以再验证一下边界编码最大正数0111111111111111 32767。最小负数1000000000000000 -32768。这两个编码务必能秒写出来。6.6 典型例题三移码与补码混合判断题目8位移码偏置128中以下哪个编码对应真值-1-1的移码 128 (-1) 127 01111111。对应补码是11111111。也就是说同一个真值-1在8位补码里是11111111在移码里是01111111。如果把两者混在一起考你就需要先在脑子里完成一次“符号位取反”的映射。这种题在浮点数章节特别多因为IEEE 754标准里阶码就用移码存储而尾数用原码或补码。把两种编码放在同一个浮点数格式里考察是很常见的。6.7 刷题建议三种训练方式第一编码转换训练。随机写10个真值比如-128、-1、-0、127、64、-64自己写出8位补码和移码再反向写回真值。这种训练每天做一次持续一周基本能形成本能。第二范围推导训练。不要背公式每次做题都从“最小刻度”出发。整数的最小刻度是1小数的小刻度是(2^{-n})然后问自己正边最大是多少负边最小是多少这个思考过程会帮你在考场上稳定输出。第三表格默写训练。把原码、反码、补码、移码在8位整数和8位小数下的范围表默写出来重点默写0的编码个数和最小负数边界。7. 一些我在实际教学和面试中反复强调的体会这篇文章写到这里我知道很多人的反应是“推得太细了考试其实不需要”。但我真正想说的是取值范围这类考点恰恰是“细推一遍受益终身”的典型。我见过太多学生靠考前突击背范围表初试能做对但复试被老师追问“为什么补码能表示-128”时直接卡壳。这其实暴露了一个根本问题没有理解补码的本质是模运算。如果你能把模运算的思路真正吃透那么后面的溢出判断、移位运算、乘法除法的硬件实现都会变得顺理成章。因为补码设计出来是为了让计算机“只做加法”而取值范围设计的核心就是“编码全部用上不浪费一个比特”。还有一个我每次都会提醒学生的细节做题时永远把“符号位、数值位”分开写不要混成一个整体。很多人在计算-128的补码时直接写“10000000”但其实正确的是“符号位1数值位0000000”。分开写的好处是一旦题目换成16位或32位你依然能快速定位每一位的含义。最后分享一个小技巧当你遇到一道取值范围题完全没思路时就把所有边界值按照“最小正数、最大正数、0、-0、最小负数、最大负数”的顺序列出来然后分别写出对应的编码。这个过程虽然有点笨但80%的题都能通过它找到正确答案。因为取值范围题考的就是边界边界写全了答案自然出来了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑