计算机中的浮点数:二进制表示与存储机制
浮点数是计算机中表示小数的核心方式,其设计巧妙但也因二进制特性存在独特的精度问题。以下从二进制小数表示、浮点数结构、IEEE 754 标准等方面详细解析:
二进制表示小数:精度问题的根源
计算机以二进制存储数据,十进制小数需转换为二进制的 “负指数幂之和”,这是浮点数精度问题的核心原因。
二进制小数的表示规则
二进制小数的整数部分与整数的二进制表示一致(如十进制5→二进制101),小数部分则通过 “2 的负指数幂累加” 表示:
- 二进制小数
b₀.b₁b₂...bₙ对应十进制的值为:b₀×2⁰ + b₁×2⁻¹ + b₂×2⁻² + ... + bₙ×2⁻ⁿ
(其中b₀是整数位,b₁~bₙ是小数位,取值为 0 或 1)
示例
- 二进制
1.011转换为十进制:1×2⁰ + 0×2⁻¹ + 1×2⁻² + 1×2⁻³ = 1 + 0 + 0.25 + 0.125 = 1.375(精确表示)。 - 十进制
0.1转换为二进制:
结果是无限循环小数0.0001100110011...,计算机无法用有限位存储,只能近似表示(这就是0.1 + 0.2 ≠ 0.3的原因)。
浮点数的组成:符号、尾数与指数
浮点数通过 “科学计数法” 的二进制形式表示,核心是用符号、尾数、指数三部分描述一个数,格式为:
1 | // 指数也叫做阶码,阶码一般是用移码表示,尾数一般是补码表示(IEEE754标准中尾数也可以用原码表示),阶码的正负叫阶符,尾数的符号位叫数符 |
如果浮点数的阶码(包括一位阶符)用R位的移码表示,尾数(包括一位数符)用M位的补码表示,则浮点数表示的数值范围时
最大正数为 $+(1-2^{-M+1})*2^{2^{R-1}-1}$
最小负数为$-1*2^{(2^{R-1}-1)}$
(计算机中基数固定为 2,因此无需存储,只需记录符号、尾数和指数)
各部分的作用
- 符号(Sign):
- 1 位二进制(0 表示正数,1 表示负数),决定数的正负。
- 尾数(Mantissa):
- 表示数的有效数字,通常为二进制小数(如
0.1011),决定数值的精度(位数越多,精度越高)。 - 为避免歧义,尾数通常采用 “规格化形式”:整数位固定为 1(如
1.011×2³的尾数存储为011,隐含整数位 1),节省存储空间。
- 表示数的有效数字,通常为二进制小数(如
- 指数(Exponent,又称阶码):
- 表示基数的幂次(如
2³中的 3),决定数值的表示范围(指数范围越大,可表示的数越大或越小)。 - 为同时表示正负指数,指数通常用 “移码” 表示(如单精度浮点数的指数偏移量为 127,实际指数 = 存储值 - 127)。
- 表示基数的幂次(如
IEEE 754 标准:单精度与双精度浮点数
IEEE 754 是目前最广泛使用的浮点数标准,定义了单精度(32 位)和双精度(64 位)两种格式,明确了各部分的位数分配:
单精度浮点数(32 位)
- 结构:
1位符号位 + 8位指数位 + 23位尾数位 - 细节:
- 指数位:偏移量为 127,可表示的指数范围为
-126 ~ +127(存储值 0~255,减去 127 后)。 - 尾数位:隐含整数位 1,实际有效位数为 24 位(23 位存储位 + 1 位隐含位),精度约为十进制 6~7 位。
- 指数位:偏移量为 127,可表示的指数范围为
双精度浮点数(64 位)
- 结构:
1位符号位 + 11位指数位 + 52位尾数位 - 细节:
- 指数位:偏移量为 1023,可表示的指数范围为
-1022 ~ +1023。 - 尾数位:隐含整数位 1,实际有效位数为 53 位,精度约为十进制 15~17 位(精度远高于单精度)。
- 指数位:偏移量为 1023,可表示的指数范围为
浮点数的关键特性与问题
1. 表示范围与精度
- 范围:由指数位决定,双精度可表示的数值范围远大于单精度(如单精度最大正数约
3.4×10³⁸,双精度约1.8×10³⁰⁸)。 - 精度:由尾数位决定,双精度的 53 位尾数可精确表示更多小数,但仍无法避免二进制无限循环小数的近似问题(如
0.1的存储误差)。
2. 对阶操作
当两个浮点数运算时(如加减),需先进行 “对阶”:
- 规则:小数向大数看齐,将指数较小的数的尾数右移(同时增大指数),使两者指数相同。
- 示例:
1.01×2³ + 1.1×2¹→ 对阶后为1.01×2³ + 0.011×2³ = 1.021×2³。
3. 特殊值
IEEE 754 定义了特殊表示:
- 无穷大(±∞):指数全为 1,尾数全为 0(如正无穷:符号位 0,指数 11111111,尾数 000…)。
- NaN(Not a Number):指数全为 1,尾数非 0,表示无效结果(如
0/0、√-1)。