原码反码补码

共 19 题
📑 题目列表 19 题
#
★★★

1. 为什么 8 位补码可表示 -128 但无法表示 +128?结合最高位位权说明?

请解释为什么 8 位补码可以表示 -128 却无法表示 +128,并结合最高位的位权说明原因?

  • 补码最高位为负位权
  • 补码表示范围推导
  • 最高位为 1 时整体恒为负数

8 位补码的最高位(第 7 位)权值为 -2^7 = -128,其余 7 位权值为 2^0 到 2^6 的正数。当最高位为 1 且其余位全为 0 时,值 = -128 + 0 = -128,可表示。而 +128 需要第 7 位为 1(其无符号权值 128),但第 7 位在补码中就是符号位、权值为 -128,任何最高位为 1 的模式都表示负数;最高位为 0 时其余 7 位最大只能到 127,同样无法达到 +128。最高位为 1 时整体总是负数,所以 +128 无法表示。

补码把最高位当作负的位权,因此取值范围是 [-128, 127]。+128 需要符号位为 1 却又作为正数,二者矛盾,故不可表示。正数最大值是 01111111 = 127。

#
★★★

2. 原码 00000000 与 10000000 都表示 0,这给减法运算带来什么问题?补码如何解决?

原码 00000000 与 10000000 都表示 0,这给减法运算带来什么问题?补码是如何解决这一问题的?

  • 原码正负零歧义
  • 补码统一 0 与减法转加法
  • 减法转为补码加法统一处理

原码中 0 有两种表示:+0 = 00000000、-0 = 10000000,比较是否相等时需要特殊处理,且运算结果可能得到 -0,造成混乱。补码中 0 只有唯一表示 00000000(-0 的补码 = 2^8 - 0 = 0,也得到 00000000),消除了正负零歧义。同时补码把减法转为加法,例如 a - b = a + (-b) 的补码,无需单独的减法器,硬件更简单。

原码的 -0 是减法运算易出错、比较需特判的根源。补码通过模运算使 -0 与 +0 重合,并用加法统一处理正负,既简化硬件又消除歧义。

#
★★★

3. 将 -1 用 8 位补码表示,并解释为何全 1 是补码表示 -1 的标准形式?

请将 -1 用 8 位补码表示,并解释为什么全 1(11111111)是补码表示 -1 的标准形式?

  • 补码计算公式
  • 全 1 模式的数值含义
  • 模 2^8 下 -1 与全 1 等价

-1 的补码 = 2^8 - 1 = 255 = 11111111(二进制)。因此 8 位补码中 -1 的位模式是全 1。原因是最高位权值为 -2^7 = -128,其余 7 位全为 1 时贡献 127,总和 -128 + 127 = -1。所以全 1 模式恰好表示 -1,这是补码的标准形式。

补码公式 -1 = 2^8 - 1 直接给出全 1。用位权验证:-128 + 127 = -1,两者一致。值得一提的是,全 1 也是无符号解读下的 255,正好是模 2^8 下 -1 的等价类。

#
★★★

4. 把十进制 -42 用 8 位原码、反码、补码分别表示,并比较三者的位模式?

请将十进制 -42 分别用 8 位原码、反码、补码表示,并比较三者的位模式?

  • 原码、反码、补码的定义
  • 负数三种编码的差异
  • 补码 = 反码 + 1 的转换关系

42 的二进制是 00101010。原码:符号位为 1,其余为绝对值,即 10101010。反码:符号位保持 1,绝对值位取反,即 11010101。补码:反码加 1,即 11010110。三者符号位相同,区别在于数值位:原码直接用绝对值,反码取反,补码取反加 1。

原码 10101010、反码 11010101、补码 11010110。可见补码 = 反码 + 1,是三者中最适合做运算的形式。验证:补码 11010110 按位权 -128+64+16+4+2 = -42,正确。

#
★★★

5. 给定 8 位原码 10110101,求其代表的十进制值,并写出其反码与补码?

给定 8 位原码 10110101,请求其代表的十进制值,并写出对应的反码与补码?

  • 原码数值解读
  • 反码与补码的转换
  • 补码按位权验证数值

原码 10110101 符号位为 1(负数),绝对值位 0110101 = 32+16+4+1 = 53,所以数值为 -53。反码:符号位不变,数值位取反,得 11001010。补码:反码加 1,得 11001011。

原码读取先看符号位,再读绝对值。反码 = 原码数值位取反,补码 = 反码 + 1。验证补码 11001011 位权:-128+64+8+2+1 = -53,正确。

#
★★★

6. 在给出原码/反码/补码定义的基础上,说明为什么计算机用补码表示有符号数?

请说明原码、反码、补码的定义,并解释为什么计算机用补码表示有符号数?

  • 三种编码的定义
  • 补码的优势
  • 补码表示范围比原码、反码多一个

原码:符号位加绝对值,0 有正负两种表示。反码:负数把原码数值位取反,0 也有两种表示。补码:负数取反加 1,0 唯一。计算机采用补码,因为:其一,补码 0 唯一,消除正负零歧义;其二,减法可统一为加法,硬件只需加法器;其三,表示范围比原码、反码多一个(能表示 -2^(n-1));其四,符号位可参与统一运算,溢出判断也简单。

补码把模运算引入负数表示,使加法电路与无符号一致,这是其被广泛采用的根本原因。代价是表示的不对称性,但收益远大于代价。

#
★★★

7. 从模 2^8 运算角度证明补码加法等价于无符号模加,并解释 -3 的补码为何是 253、与 5 相加得到 2 的位运算过程?

请从模 2^8 运算的角度证明补码加法等价于无符号模加,并解释 -3 的补码为何是 253,以及它与 5 相加得到 2 的位运算过程?

  • 模 2^n 运算
  • 补码加法与无符号加法一致
  • 高位进位丢弃即模 2^8 运算

在模 2^8 意义下,-3 = 2^8 - 3 = 253,因此 -3 的补码位模式就是 253(11111101)。补码加法 -3 + 5 = 2,等价于无符号 253 + 5 = 258,而 258 mod 256 = 2。位运算过程:11111101 + 00000101 = 1 00000010,低 8 位为 00000010 = 2,进位 1 被丢弃,正好是模 2^8 的结果。所以补码加法与无符号加法在位数截断后完全一致。

补码把负数映射到模 2^8 的补余,使减法、加法都变成无符号模加。硬件只需一套无符号加法器,进位自然丢弃即是模运算。这证明补码与无符号加法的统一性。

#
★★

8. 给定 8 位补码 11110000,求其代表的十进制值,并验证按位取反加 1 后等于 0?

给定 8 位补码 11110000,请求其代表的十进制值,并验证按位取反加 1 后等于 0?

  • 补码读取十进制值
  • 取反加一的性质
  • 取反加一得到相反数

补码 11110000 最高位为 1,是负数。其值 = -128 + 64 + 32 + 16 = -128 + 112 = -16。按位取反得 00001111,加 1 得 00010000 = 16。验证:-16(原数)与 16(取反加一)相加 = 0,符合取反加一得到相反数的性质。

取反加一对任意补码 x 得到 -x,因此 x + (~x + 1) = 0。这里 11110000 取反加一为 00010000,即 16,与 -16 互补,验证成立。

#
★★

9. 计算 8 位补码 10000000 与自身的加法结果,按补码定义解释溢出?

请计算 8 位补码 10000000 与自身相加的结果,并按补码定义解释溢出?

  • 补码加法溢出
  • 8 位补码范围
  • 两负数相加结果符号位为 0 判定溢出

10000000 是 -128。10000000 + 10000000 = 1 00000000,低 8 位为 00000000 = 0,但数学上 -128 + (-128) = -256,超出 8 位补码范围 [-128, 127]。结果本应为 -256,却得到 0,明显错误,产生溢出。因为两个负数相加所得符号位为 0,符号不符合预期,属于溢出。

溢出判断:两个负数相加结果应为负,但这里符号位为 0,是正数,说明溢出。用双符号位或看进位:最高位产生进位(1)而符号位进位为 0,发生溢出。

#
★★

10. 原码与反码在对 0 的表示上各有什么问题?补码为何消除这一歧义?

原码与反码在对 0 的表示上各有什么问题?补码为什么能消除这一歧义?

  • 原码、反码的 ±0
  • 补码模运算消除 ±0
  • 腾出的位模式 10000000 表示 -128

原码中 +0 = 00000000、-0 = 10000000;反码中 +0 = 00000000、-0 = 11111111。两种编码都有两个 0,比较相等、判断符号时需特判,运算也可能得到 -0,造成混乱。补码中 -0 的补码 = 2^8 - 0 = 0,即 00000000,与 +0 重合,故 0 只有唯一表示,消除了歧义,也把 10000000 腾出来表示 -128。

补码通过模 2^n 定义,使 -0 映射到 0 本身,正负零合一。唯一 0 让比较和运算更简单,同时多出一个可用位模式表示 -2^(n-1)。

#
★★

11. 补码的运算性质包括减法转加法与溢出判定(双符号位)两个方面?

请说明补码的运算性质,包括减法转加法以及基于双符号位的溢出判定方法?

  • 减法转加法
  • 双符号位溢出判定
  • 符号位进位与最高位进位不一致判定溢出

补码最重要的性质是减法可转为加法:a - b = a + (-b)。由于 -b 的补码就是 b 取反加一,硬件只需加法器即可完成减法和。溢出判定的一种方法是双符号位(变形补码):运算时用两个符号位,若结果两个符号位不同(如 01 或 10),说明溢出。具体地,00 表示正数无溢出,11 表示负数无溢出,01 表示正溢出(上溢),10 表示负溢出(下溢)。

双符号位判溢出利用最高位进位与次高位进位是否一致判断:若符号位进位与最高数位进位不同则溢出。这是硬件常用的溢出检测手段,比单看符号位更可靠。

#
★★

12. 将 8 位补码 0x80(-128)符号扩展到 16 位得 0xFF80,解释为什么高位全填 1 仍表示同一个负数?

将 8 位补码 0x80(-128)符号扩展到 16 位得到 0xFF80,请解释为什么高位全填 1 仍表示同一个负数?

  • 符号扩展
  • 补码位权下高位填充 1 的语义
  • 符号扩展保持数值不变的位权原理

0x80 = 10000000 是 8 位补码 -128。符号扩展到 16 位时,把符号位(1)复制到新增的高 8 位,得到 11111111 10000000 = 0xFF80。验证其值:16 位补码中最高位权值为 -2^15 = -32768,其余各位求和 = 32768 - 128 = 32640,总和 -32768 + 32640 = -128。新增的高位全 1 并没有改变数值,因为它们在 16 位补码的负位权下,通过模运算等价于原 8 位数的符号扩展。

符号扩展保持负数不变,因为高位填 1 等同于把模 2^8 的数在模 2^16 下取同一等价类。对正数,高位填 0 保持正数值不变。这是 C 语言中 char 提升到 int 时保值的关键。

#
★★

13. 证明按位取反加一的自反性,即对任意 8 位补码 x,~x+1 得到 -x 且再取一次仍回到 x?

请证明按位取反加一的自反性:对任意 8 位补码 x,~x+1 得到 -x,而且再取一次仍回到 x?

  • 取反加一的代数性质
  • 自反性证明
  • x + ~x = 全 1 = -1 的代数关系

对任意 x,x + (~x) = -1(全 1),因为每一位 x 与 ~x 相加都是 1。因此 x + (~x + 1) = -1 + 1 = 0,即 ~x + 1 = -x,所以取反加一得到相反数。再取一次:~(~x+1)+1 = -(-x) = x,回到原值,证明自反性。例如 x = 5 = 00000101,~x+1 = 11111010+1 = 11111011 = -5,再取反加一得 5。

关键在于 x + ~x = 全 1 = -1,从而 ~x + 1 = -x。由于相反数运算是对合(involution),两次运算回到原值。这是 C 中 ~x + 1 求负的重要依据。

#

14. 在 8 位补码下计算 01111111 + 00000001,结果是多少?哪种标志位会被置位?

在 8 位补码下计算 01111111 + 00000001,结果是多少?哪种标志位会被置位?

  • 补码加法溢出
  • 标志位(OF/CF)
  • OF 与 CF 在带符号与无符号视角的区别

01111111 + 00000001 = 10000000。按位计算 01111111 + 00000001 = 10000000(进位进入符号位)。01111111 = 127,00000001 = 1,数学和 = 128,但 8 位补码结果 10000000 = -128,明显错误,发生溢出。最高位进位(无符号进位)产生 CF,但更重要的是符号位进位与最高数位进位不一致(无符号最高位进位为 0,符号位进位为 1),产生带符号溢出标志 OF。

01111111 是最大正数 127,加 1 溢出为 -128。这是正溢出,置位 OF(溢出标志)。因为无符号看 CF(进位),有符号看 OF(溢出),本例是带符号溢出,OF 置位。

#

15. 补码边界处 INT_MIN 与 INT_MAX 的位模式与溢出行为是怎样的?

请说明补码的边界值 INT_MIN 与 INT_MAX 的位模式及其溢出行为?

  • INT_MIN/INT_MAX 位模式
  • 边界溢出行为
  • 负数比正数多一个的不对称性

32 位补码中 INT_MAX = 01111111111111111111111111111111(0x7FFFFFFF),INT_MIN = 10000000000000000000000000000000(0x80000000)。INT_MAX + 1 在 C 中是未定义行为(UB),但在常见实现中会回绕到 INT_MIN。INT_MIN - 1 同样 UB,常回绕到 INT_MAX。INT_MIN 取负(-INT_MIN)也为 UB,因为 +INT_MIN 无对应正数。在硬件层面,INT_MAX+1 产生正溢出,置位 OF。

INT_MAX 是 0x7FFFFFFF,INT_MIN 是 0x80000000,二者不对称:负数比正数多一个。C 标准将有符号溢出定为 UB,因此编译器可随意优化,需依赖硬件检测或使用无符号/饱和运算。

#

16. 位宽与符号扩展中,有符号/无符号隐式转换的陷阱有哪些?

请解释位宽与符号扩展中的有符号/无符号隐式转换陷阱?

  • 隐式转换规则
  • 符号扩展陷阱
  • 有符号转无符号后负数便成很大的正数

当有符号与无符号整数参与运算时,C 会进行隐式转换。常见陷阱:短的有符号数提升到更长位宽,若按符号扩展则保持数值,若按无符号扩展(高位填 0)则会改变数值。例如 (char)-1 提升到 int 符号扩展为 -1,但若先转 unsigned char 再扩展则变成 255。此外,有符号与无符号混合比较时,有符号会被转成无符号,导致负数变成很大的正数,比较结果反直觉。

陷阱根源在于符号扩展与非符号扩展的区分,以及混合运算时向无符号转换的规则。例如 -1 < 0u 的结果是 false,因为 -1 转成无符号后是很大的数。避免方法:显式强转、避免混合比较。

#

17. 浮点数的 IEEE 754 表示中符号、指数与尾数如何划分?

请说明 IEEE 754 浮点数的表示结构,包括符号、指数、尾数三部分的含义?

  • IEEE 754 三字段
  • 规格化与非规格化
  • 隐含整数位 1 扩大有效精度

IEEE 754 将浮点数表示为 (-1)^s × 1.f × 2^(e-bias),其中 s 是符号位,e 是移码表示的指数(单精度 8 位,偏移 127),f 是尾数(单精度 23 位,隐含整数位 1)。单精度共 32 位:1 位符号 + 8 位指数 + 23 位尾数;双精度 64 位:1 + 11 + 52。指数全 0 表示次正规数或 0,全 1 表示 Inf 或 NaN。规格化数隐含一位开头的 1,扩大了有效精度。

用移码表示指数可方便比较大小,隐含 1 位省去存储空间。IEEE 754 的设计兼顾精度、范围与特殊值(0、Inf、NaN)的表示。

#

18. 移码与阶码中,浮点指数为什么用偏置表示?

请解释移码与阶码的概念,以及浮点指数为什么用偏置(移码)表示?

  • 移码定义
  • 偏置表示的优势
  • 指数域顺序与真实指数一致便于比较

移码(biased representation)是把真实指数加上一个偏置值得到存储值。单精度偏置 127,双精度偏置 1023。存储的实际指数 = 真实指数 + 偏置。用偏置表示的原因:一是使指数域从全 0 到全 1 单调递增,便于浮点数的排序比较(无需先判断符号);二是使指数可表示负数(负指数通过小于偏置的存储值表示),且全 0 和全 1 保留给特殊值(0、次正规、Inf、NaN)。

相比补码,移码让指数域的数值顺序与真实指数顺序一致,比较两个浮点数时先比指数域即可,硬件更简单。这是 IEEE 754 采用偏置的关键理由。

#

19. 8 位补码表示范围为何是 [-128, 127] 而非 [-127, 127],正数与负数的个数为何不对称?

请解释 8 位补码表示范围为何是 [-128, 127] 而非 [-127, 127],以及正数与负数的个数为何不对称?

  • 补码范围推导
  • 补码 0 唯一导致的不对称
  • 256 个位模式中 0 仅占一个

8 位共 256 个位模式。原码、反码中 0 占两个模式(+0、-0),所以正负各 127 个,范围为 [-127, 127]。补码中 0 只有一个模式(00000000),多出的一个模式 10000000 被用作 -128(最负数),因此负数有 128 个,正数 127 个,范围为 [-128, 127]。不对称正是补码 0 唯一表示带来的结果。

256 个模式中,0 占一个,剩下 255 个,负数多占一个(128 个),正数 127 个。所以最小负数 -128 无对应正数 +128,这是补码不对称的必然。