1 机器数与真值
1.1 机器数
在计算机系统中,所有数值均以二进制形式存储和处理,这些二进制编码被称为机器数。
机器数不仅表示数值的大小,还需承载符号信息(正负号)。为实现符号表示,计算机采用最高位作为符号位的编码规则:
- 符号位为 0:表示正数;
- 符号位为 1:表示负数。
例如,8 位二进制数 0110 0101 中,最高位 0 表明这是一个正数,其余位表示数值部分。这种符号与数值结合的编码方式,是计算机处理有符号数的基础。
1.2 真值
由于机器数包含符号位,其形式值(直接按二进制转换的结果)与真值(实际表示的数值)可能存在差异。以 8 位机器数 1000 0001 为例:
- 形式值:若直接按无符号数计算,该机器数 1000 0001 等于 129;
- 真值:若按有符号数解析,该机器数最高位 1 表示负数,其余位 000 0001 对应数值 1,因此真值为 -1。
这种差异源于机器数的编码规则。计算机需通过符号位判断数值的正负,再结合数值位还原真值。例如,正数的真值与其形式值一致,而负数的真值通常通过补码形式存储。
2 原码、反码、补码详解
2.1 原码:符号与数值的映射
原码是最直观的编码方式,其表示与机器数真值表示的一样,规则如下:
- 符号位:最高位表示符号,0 为正,1 为负;
- 数值位:其余位直接表示数值的绝对值。
规则细化:
- 正数的原码:符号位为 0,数值位为其二进制表示。
- 示例:+1 的原码为 [0000 0001]。
- 负数的原码:符号位为 1,数值位为其绝对值对应的二进制。
- 示例:-1 的原码为 [1000 0001]。
- 0 的原码:
- +0:符号位为 0,数值位全为 0,即 [0000 0000]。
- -0: 符号位为 1,数值位全为 0,即 [1000 0000]。
特点与问题:
- 直观但低效:
- 原码直接反映了符号与数值的关系,使得人们能够直观地理解其表示的数值。
- 然而,在进行加减法运算时,原码需要额外处理符号位,这增加了硬件实现的复杂性。
- 零的冗余:
- 原码中存在 +0 和 -0 两种表示形式,这导致了逻辑上的歧义。
- 在实际的计算机系统中,这种冗余通常是不必要的,且可能引发一些潜在的问题。
2.2 反码:原码到补码的桥梁
反码是原码的改进形式,主要用于计算补码或反向解析补码。规则如下:
- 正数的反码:与原码相同。
- 示例:+1 的原码为 [0000 0001],反码仍为 [0000 0001]。
- 负数的反码:符号位不变,数值位逐位取反(0→1,1→0)。
- 示例:-1 的原码为 [1000 0001],反码为 [1111 1110]。
- 0 的反码:
- +0:+0 的原码为 [0000 0000],对应的反码为 [0000 0000]。
- -0: -0 的原码为 [1000 0000],对应的反码为 [1111 1111]。
作用与局限性:
- 过渡作用:反码是补码计算的前置步骤。在补码的计算中,通常先求出反码,然后在反码的基础上加 1 即可得到补码。
- 现代计算机中不直接使用:现代计算机中不直接使用反码进行运算。反码仅作为中间表示形式存在,实际的运算(如加法、减法等)仍以补码为核心。
2.3 补码:计算机运算的核心
计算机底层以二进制形式存储数据,这是因为二进制系统仅包含 0 和 1 两个状态,非常适合于电子设备的开关状态表示,从而实现数据的稳定存储与处理。然而,直接存储数值的二进制形式在处理有符号数(即正负数)时并不高效,因为需要额外的逻辑来区分正负并处理符号位。
为了统一处理有符号数并简化运算逻辑,计算机采用了补码作为有符号数值的存储形式。补码是一种数值编码方式,它能够将正数和负数统一表示为二进制形式,并且使得加减运算可以像处理无符号数一样简单。规则如下:
- 正数的补码:与原码、反码相同【三码合一】。
- 示例:+1 的原码、反码、补码均为 [0000 0001]。
- 负数的补码:反码基础上末尾加 1。
- 示例:-1 的原码为 [1000 0001],反码为 [1111 1110],补码为 [1111 1111]。
- 0 的补码:0 的补码唯一表示为 [0000 0000]。
- +0 的原码为 [0000 0000],反码为 [0000 0000],对应的补码为 [0000 0000]。
- -0 的原码为 [1000 0000],反码为 [1111 1111],对应的补码为 [0000 0000],最高位的进位被丢弃了。
- 所以,0 的补码唯一表示为 [0000 0000],消除了原码和反码中 +0 和 -0 的冗余。
2.4 三码规则速览
- 正数:
- 正数的原码、反码、补码均相同,实现 “三码合一”。
- 负数:
- 原码:以符号位 1 开头,后跟其绝对值对应的二进制数。
- 反码:保持原码符号位不变,其余数据位逐位取反(0→1,1→0)。
- 补码:在反码的基础上末尾加 1。
- 0:
- 原码和反码中存在正负 0 的区分,而补码则确保了 0 的唯一表示。
示例对比(以 8 位二进制表示 +1 、-1 、+0、-0):
数值 | 原码 | 反码 | 补码 |
---|---|---|---|
+1 | [0000 0001] | [0000 0001] | [0000 0001] |
-1 | [1000 0001] | [1111 1110] | [1111 1111] |
+0 | [0000 0000] | [0000 0000] | [0000 0000] 唯一 0 |
-0 | [1000 0000] | [1111 1111] |
3 补码负数全 0/1 数值表示规则
在计算机科学中,有符号整数常采用补码表示法。
当有符号整数的二进制表示全为 1 时,如 8 位的 1111 1111、16 位的 1111 1111 1111 1111 或 32 位的 1111 1111 1111 1111 1111 1111 1111 1111,该整数通常表示 -1。这是补码编码规则的直接体现,在计算机系统中极为常见。
当有符号整数的二进制最高位(符号位)为 1,其余位为 0 时,表示的是 -2 的(位数 - 1)次方。具体来说,当最高位为 1,其余位为 0 时,这个数表示的是该位数下能表示的最小负数,即 -2^(n - 1)(n 为二进制位数)。
例如:
- 4 位二进制数 1000,表示 -2^(4 - 1) = -2^3 = -8。
- 8 位二进制数 1000 0000,表示 -2^(8 - 1) = -2^7 = -128。
- 16 位二进制数 1000 0000 0000 0000,表示 -2^(16 - 1) = -2^15 = -32768。
4 计算机采用补码的原因
4.1 补码运算优势
计算机使用补码进行运算的主要原因是为了简化硬件设计和提高计算效率。补码的设计巧妙地解决了原码表示法中存在的问题,使得计算机能够更高效地执行加减法运算。
原码表示法的问题
在原码表示法中,最高位是符号位,0 表示正数,1 表示负数。然而,这种表示方法在进行减法运算时会导致硬件设计复杂,因为需要额外处理符号位。例如,使用原码进行减法运算时,计算机需要判断两个数的符号,然后根据符号执行不同的操作,这增加了硬件的复杂性和运算时间。
补码表示法的优点
补码表示法通过将减法运算转换为加法运算,简化了硬件设计。在补码表示法中,正数的补码与原码相同,负数的补码是其原码取反加 1。这种表示方法使得计算机在执行加减法运算时,只需进行加法操作,无需额外处理符号位,从而提高了计算效率。
例如,计算 2 - 2 的过程:
- 使用原码表示法:2 的原码是 0000 0010,-2 的原码是 1000 0010,直接进行减法运算需要额外处理符号位。
- 使用补码表示法:2 的补码是 0000 0010,-2 的补码是 1111 1110,将减法转换为加法运算,即 2 + (-2) 的补码,结果为 0000 0000,表示 0,计算过程简单且高效。
补码运算的正确性
补码运算的正确性可以通过上述例子验证。使用补码进行运算时,符号位也参与运算,并且可以得到正确的计算结果。这不仅简化了硬件设计,还提高了运算速度和准确性。
4.2 补码存储优势
计算机使用补码来存储数据的主要原因是为了简化硬件设计和提高计算效率,同时也为了能够表示和处理负数。
无符号整数存储
在无符号整数的存储中,所有的二进制位都用于表示数值的大小。例如,4 个二进制位可以表示从 0 到 15 的整数。这种表示方法简单直接,但由于没有符号位,无法表示负数。
有符号整数存储
为了表示负数,计算机使用补码来表示有符号整数。
- 在补码表示法中,最高位是符号位,0 表示正数,1 表示负数。
- 正数的补码与原码相同,负数的补码是其原码取反加 1。
例如,使用 4 个二进制位表示有符号整数时:
- 正数 0 的补码是 0000,表示十进制的 0。
- 正数 1 的补码是 0001,表示十进制的 1。
- 负数 -1 的补码是 1111,表示十进制的 -1。
- 负数 -8 的补码是 1000,表示十进制的 -8。
这种表示方法使得计算机能够在一个固定的位数内表示更大的数值范围,同时也简化了加减法运算的硬件设计。
补码存储的优势
使用补码存储数据的主要优势在于:
- 统一了加减运算:补码表示法将减法运算转换为加法运算,简化了硬件设计。
- 扩大了数值范围:在相同的位数下,补码表示法能够表示更大的数值范围,包括正数和负数。
- 提高了计算效率:由于加减运算的统一,计算机能够更高效地执行运算。
5 原码与补码的相互转换
在计算机中,正数的原码、反码与补码均相同,可简称为 “三码合一”。对于负数而言,其原码与补码之间的转换可通过数值位按位取反后加一(同时保持符号位不变)来实现。
5.1 原码 → 补码
转换步骤:
- 保持符号位:负数的原码最高位为 1,表示符号为负。
- 数值位取反:将原码中除符号位外的其余位按位取反。
- 末尾加 1:将取反后的结果末尾加 1,得到的就是该负数的补码。
示例说明:
例如,对于负数 -5,用 8 位二进制表示:
- 原码:1000 0101
- 数值位取反:1111 1010
- 末尾加 1:1111 1011(这就是 -5 的补码)
5.2 补码 → 原码
方法一:减 1 取反
此方法相当于是原码 → 补码运算的逆运算,以补码 1111 1011(-5 的补码)为例:
- 符号位不变,数值位减 1
- 1111 1011 → 1111 1010(末尾减 1,符号位保留)
- 数值位取反
- 1111 1010 → 1000 0101(数值位从 111 1010 → 000 0101,符号位不变)
- 结果 1000 0101 是 -5 的原码,验证正确。
方法二:取反加 1
此方法与原码 → 补码运算步骤相同,同样以补码 1111 1011(-5 的补码)为例:
- 符号位不变,数值位取反
- 1111 1011 → 1000 0100(数值位 111 1011 → 000 0100,符号位不变)
- 末尾加 1
- 1000 0100 + 1 = 1000 0101
- 结果仍为 -5 的原码,与方法一一致,验证正确。
关键点总结
- 两种方法等价性
- 方法一是方法二的逆过程,数学上等价。
- 无论从补码 → 原码还是原码 → 补码,操作均围绕 “取反加 1” 或其逆运算 “减 1 取反” 展开。
- 符号位处理
- 两种方法均保持符号位不变,仅操作数值位。
注意事项
- 补码的唯一性:对于负数,补码与原码一一对应,但正数的补码与原码相同(无需转换)。
- 边界情况:1000 0000(-128 的补码)无法通过 “减 1 取反” 或 “取反加 1” 得到原码(因在 8 位二进制中,原码表示范围为 -127 ~ +127)。
6 计算机内部补码运算过程
在计算机中,减法运算通常通过补码来实现。下面以计算 10 - 12 为例,详细描述使用补码进行计算的过程。
1. 将十进制数转换为二进制原码
- 10 的二进制原码为:0000 1010
- -12 的二进制原码为:1000 1100(这里最高位为符号位,1 表示负数)
2. 求 -12 的补码
- 先求 -12 的反码:将 -12 的原码除符号位外的其他位取反,得到 1111 0011。
- 再求 -12 的补码:在反码的基础上加 1,得到 1111 0100。
3. 进行二进制加法运算
- 将 10 的原码(即补码) 0000 1010 与 -12 的补码 1111 0100 进行二进制加法运算,得到 1111 1110。
4. 将结果转换为十进制数
- 得到的二进制结果 1111 1110 是补码形式,需要先转换为原码。
- 因为最高位为 1,表示结果为负数,求其原码:
- 方法一(减 1 取反):先将 1111 1110 减 1 得到 1111 1101,再将数值位取反得到 1000 0010。
- 方法二(取反加 1 ):先将 1111 1110 取反得到 1000 0001,再加 1,得到1000 0010。
- 1000 0010 对应的十进制数为 -2。
7 三码快速转换工具
为了加速开发进度,我们可以借助一些工具来实现原码、反码和补码之间的快速转换。以下是两种可行的方法:
7.1 电脑计算器转换
1. 按下电脑键盘上的 Windows 键,打开开始菜单。在搜索框中输入 “计算器”,并打开计算器应用程序。
2. 在计算器界面中,切换至 “程序员” 模式。
3. 在程序员模式下,你可以输入相应的二进制、八进制、十进制或十六进制数据,计算器会自动进行不同进制之间的转换,并直接显示这些数值在补码表示法下的对应值,方便你查看原码、反码(虽然计算器不直接显示反码,但你可以通过补码间接理解)和补码的具体数值。请注意,计算器显示的数据通常是补码形式,因为这是计算机内部存储和运算的主要编码方式。
7.2 在线工具转换
除了电脑自带的计算器程序,你还可以选择使用一些在线的转换工具。这些工具通常提供了更为直观和便捷的操作界面,只需输入需要转换的数值和选择相应的进制,即可快速得到转换结果。
在线原码/反码/补码计算器:https://www.lddgo.net/convert/number-binary-code