3、数据表示与运算基础:定点数、浮点数(IEEE 754)、原码反码补码、字符编码与校验码

计算机体系结构的第一块基石,是解决“数据如何在机器中被表示与运算”的问题。冯·诺依曼体系结构中,一切信息(数值、字符、指令)最终都转化为二进制比特流。然而,二进制串本身是“无意义”的,其含义完全取决于解释规则。本章将系统梳理数值型数据的定点与浮点表示、机器数编码方案(原码/反码/补码)、字符编码标准以及数据校验机制,帮助读者建立从“物理比特”到“逻辑数值”的完整映射认知。

数据表示与运算基础——知识框架与编码关系 数据表示体系 定点数(纯整数/纯小数) 原码/反码/补码 符号位+数值域 浮点数(IEEE 754) 符号位+阶码+尾数 规格化/非规格化 字符编码(ASCII/Unicode) ASCII→UTF-8/UTF-16 校验码(奇偶/CRC/海明) 检错/纠错能力 核心:同一比特串在不同解释规则下代表不同数值/字符,编码方案决定运算正确性与精度边界

上图展示了本章知识体系的整体框架。数值数据(定点与浮点)关注“如何用有限位宽表达实数范围与精度”,机器数编码(原码/反码/补码)解决“如何让加减法统一为加法运算”,字符编码解决“非数值信息的二进制映射”,而校验码则保障数据在存储或传输过程中的完整性。四者相互独立又彼此关联,共同构成计算机运算单元的输入输出基础。

3.1 定点数表示与机器数编码

3.1.1 核心原理:定点数的格式与局限

定点数约定小数点位置固定不变。常见格式有两种:纯整数(小数点固定在最低位之后)和纯小数(小数点固定在符号位之后)。例如,8位定点整数可表示范围是 -128~127(补码)或 -127~127(原码/反码)。定点数的优势在于运算简单、硬件实现成本低,但动态范围小,无法同时满足大范围和高精度的需求。例如,用16位定点整数表示圆周率,只能取3,精度损失严重。

3.1.2 判断方法:原码、反码、补码的转换规则

对于正数,三种编码的符号位为0,数值位与真值相同。对于负数,转换规则如下:

  • 原码:符号位为1,数值位为值二进制表示。
  • 反码:符号位为1,数值位为原码数值位按位取反。
  • 补码:符号位为1,数值位为反码数值位加1(即原码数值位取反加1)。

补码的核心优势在于:减法可以转化为加法,且0的表示唯一(+0和-0的补码均为00000000)。例如,计算 5 - 3 时,可转换为 5 + (-3) 的补码运算:00000101 + 11111101 = 1 00000010,丢弃最高位进位后得到 00000010,即2。

真值原码(8位)反码(8位)补码(8位)
+7000001110000011100000111
-7100001111111100011111001
+0000000000000000000000000
-0100000001111111100000000(唯一)

3.1.3 案例拆解:补码运算的溢出判断

假设使用4位补码表示整数,计算 7 + 1。7的补码为0111,1的补码为0001,相加得1000。由于符号位从0变为1,且最高数值位产生进位而符号位无进位,发生溢出。判断溢出的常用规则是:最高位进位与次高位进位异或为1时溢出。此例中,次高位(bit2)进位为1,最高位(bit3)进位为0,异或结果为1,故溢出。实际结果为-8,显然错误。这说明定点数运算必须考虑位宽限制,否则结果不可信。

常见误区:初学者常混淆“进位”与“溢出”。进位是指最高位产生的进位输出,而溢出是指运算结果超出当前位宽可表示的范围。有进位不一定溢出(如补码加法中丢弃进位是正常操作),无进位也可能溢出(如正数+正数得到负数)。

3.2 浮点数表示:IEEE 754标准

3.2.1 核心原理:科学计数法的二进制实现

IEEE 754标准定义了浮点数的存储格式,以32位单精度(float)为例,其布局为:1位符号位(S)、8位阶码(E)、23位尾数(M)。真值计算公式为:(-1)^S × 1.M × 2^(E-127)。其中,阶码采用偏置码表示,单精度偏置值为127,双精度为1023。尾数采用隐含位技术,即规格化数的小数点前一位恒为1,不显式存储,从而多获得1位精度。

3.2.2 判断方法:规格化与非规格化数的识别

  • 规格化数:阶码E不全为0且不全为1,此时尾数隐含1,即1.M。
  • 非规格化数:阶码E全为0,此时尾数隐含0,即0.M,用于表示接近0的极小数值。
  • 特殊值:阶码全为1且尾数全为0表示无穷大(±∞);阶码全为1且尾数非0表示NaN(非数值)。

例如,将十进制数 -12.75 转换为单精度浮点数:符号位S=1;12.75的二进制为1100.11,规格化为1.10011 × 2^3;阶码E=3+127=130,即10000010;尾数M=10011000000000000000000。最终存储为:1 10000010 10011000000000000000000。

3.2.3 案例拆解:浮点数精度损失与比较陷阱

在C语言中执行 float a = 0.1f; float b = 0.2f; if (a + b == 0.3f) 通常为假。原因是0.1和0.2在二进制中均为无限循环小数,存储时被截断,导致累加结果与0.3的存储值存在微小差异。实际工程中,应使用误差容限比较:fabs(a + b - 0.3f) < 1e-6。此外,浮点数运算不满足结合律,例如 (1e20 + 1) - 1e20 的结果为0,而 1e20 + (1 - 1e20) 的结果为0,但 (1e20 - 1e20) + 1 的结果为1。这说明运算顺序会影响精度。

经验提醒:在嵌入式或科学计算中,若对精度有严格要求,应避免使用浮点数,改用定点数或十进制字符串运算。浮点数适合表示动态范围大但精度要求不高的场景,如物理模拟、图形渲染。

3.3 字符编码与校验码

3.3.1 核心原理:从ASCII到Unicode的演进

ASCII码使用7位二进制表示128个字符(含控制字符),扩展ASCII使用8位表示256个字符。但ASCII无法覆盖中文、日文等非拉丁文字。Unicode字符集为每个字符分配唯一的码点(如“中”的码点为U+4E2D),而UTF-8是Unicode的一种变长编码方案,用1~4个字节表示一个字符,兼容ASCII,且无字节序问题。例如,“A”的UTF-8编码为0x41,“中”的编码为0xE4 0xB8 0xAD。

3.3.2 判断方法:校验码的检错与纠错能力

校验码用于检测或纠正数据在传输/存储中的错误。常见方案包括:

  • 奇偶校验:在数据位后附加1位,使整个码字中1的个数为奇数(奇校验)或偶数(偶校验)。只能检测奇数位错误,无法纠错。
  • CRC(循环冗余校验):将数据视为多项式,除以生成多项式,余数作为校验码。可检测突发错误,广泛应用于网络通信(如以太网帧的FCS)。
  • 海明码:在数据位之间插入多个校验位,不仅能检测错误,还能定位并纠正单比特错误。例如,8位数据需要4个校验位,形成12位码字。
校验方式校验位数量检错能力纠错能力典型应用
奇偶校验1奇数位错误无UART串口
CRC-3232突发错误(长度≤32)无以太网、ZIP压缩
海明码log2(n)+1多比特错误(部分)单比特错误ECC内存

3.3.3 案例拆解:海明码的编码与纠错过程

以4位数据D3D2D1D0=1011为例,需要3个校验位P2P1P0,码字排列为P2P1D3P0D2D1D0(位置1~7)。校验位覆盖规则:P0覆盖位置1,3,5,7;P1覆盖位置2,3,6,7;P2覆盖位置4,5,6,7。计算各校验位使对应组内1的个数为偶数:P0=D3⊕D2⊕D0=1⊕0⊕1=0;P1=D3⊕D1⊕D0=1⊕1⊕1=1;P2=D3⊕D2⊕D1=1⊕0⊕1=0。发送码字为0101011。若接收端收到0101111(位置6发生错误),则重新计算各组校验:组0(位置1,3,5,7)=0⊕1⊕1⊕1=1;组1(位置2,3,6,7)=1⊕1⊕1⊕1=0;组2(位置4,5,6,7)=1⊕1⊕1⊕1=0。将组号组合为二进制100(即4),表示位置4出错?实际错误位置为6,但计算得4,说明规则需按位置编号的二进制位来分组。正确做法:将出错位置编号的二进制位对应校验组,此处位置6的二进制为110,即组2和组1出错,组0正确,组合为110(十进制6),定位到位置6,取反即可纠正。

总结复盘:数据表示的核心矛盾是“有限位宽 vs 无限实数”。定点数牺牲范围换取精度和速度,浮点数牺牲精度换取大动态范围,字符编码牺牲存储空间换取通用性,校验码牺牲冗余位换取可靠性。在实际系统设计中,必须根据应用场景(如传感器数据采集、金融计算、文本处理)选择合适的表示方案,并时刻警惕溢出、精度损失和编码不一致问题。