浮点数与IEEE 754
定义
二进制浮点数沿用科学计数法:先把数写成整数部分为一位的二进制小数,再乘以2的幂,即 。IEEE 754把符号、指数、尾数三段装进定长字段,其中指数存成偏移后的 (单精度),数值由下式还原:
32位单精度的字段划分如下。
| 字段 | 位数 | 位置 | 含义 |
|---|---|---|---|
| 符号 | 1 | 第31位 | 0为正,1为负 |
| 阶码 | 8 | 第30~23位 | 偏移后的指数, |
| 尾数 | 23 | 第22~0位 | 小数点后的部分,隐含前导1 |
写成位串时依次是S EEEEEEEE FFF…F,阶码在前、尾数在后。记尾数位为 ( 紧接小数点),则
这两个式子是换算的依据:先拆出三段,把阶码减127得到实际指数 ,再把尾数按 展开,最后加上隐含的1。
性质
阶码用偏移表示
指数可能是负的,例如 表示很小的数。如果阶码直接存带符号数,比较两个浮点数的大小时就得先看阶码的符号位,硬件无法把位串当作无符号整数直接比较。IEEE 754给指数统一加一个偏移:单精度 ,双精度 。这样阶码字段本身就是无符号整数,指数的大小顺序与位串的字典序一致。
单精度阶码8位,规格化数对应 ,即 ;双精度阶码11位,对应 。
隐藏的前导1
规格化之后整数部分总是1:整数部分若为0,左移一位、阶码加一即可;若大于1,则还没有规格化完。既然总是1,就不必存进尾数,省下一位。因此23位尾数实际提供24位有效数字,双精度的52位尾数提供53位。
精度与范围
| 格式 | 总位数 | 阶码位 | 尾数位 | 偏移 | 十进制有效数字 |
|---|---|---|---|---|---|
| 单精度 | 32 | 8 | 23 | 127 | 约7位 |
| 双精度 | 64 | 11 | 52 | 1023 | 约15~16位 |
范围由阶码决定,精度由尾数决定。单精度能表示的最大规格化数约为 ,双精度约为 。C中的float、double分别对应这两种格式。
误差来源
十进制小数转二进制时,若最简分数的分母含有2以外的质因子,展开就无限循环。 的二进制是 ,规格化后为 ,尾数需要无限多位。23位尾数只能截断或就近舍入,存进去的值与 相差约 。
运算中还要对齐阶码、对结果舍入,误差会逐步累积。例如:
print(0.1 + 0.2) # 0.30000000000000004print(0.1 + 0.2 == 0.3) # False第二行输出False,说明两个结果不相等。比较浮点数应写成 的形式,而不是直接用等号。
例子
解码0 10000010 101000…0
-
拆字段:;;尾数前三位是 ,其余为0。
-
定符号:,是正数。
-
算指数:。
-
算尾数:,加上隐含的1得 。
-
合成:。
为什么 不等于
、、 在二进制下都是无限循环小数,存入时各自被舍入成最接近的可表示值。三个值都不等于原来的十进制小数,相加的结果自然与 的存储值不同,差额在双精度下约为 量级。
这不是浮点数算错了,而是舍入的必然结果。把判断改成 后,比较就能通过。
练习
位串
0 10000001 100000…0表示的十进制值是 。参考解答
,实际指数 ;尾数 ,加上隐含的1得 。。
填出IEEE 754各字段的位数。
单精度的阶码占 位。
参考解答
单精度共32位:符号1位、阶码8位、尾数23位。
单精度的尾数占 位。
参考解答
尾数不存储隐含的前导1,所以只占23位。
双精度的尾数占 位。
参考解答
双精度共64位:符号1位、阶码11位、尾数52位。
的单精度表示中,阶码字段的8位二进制是 (只填0和1)。
参考解答
,实际指数 ,阶码 。尾数位全为0。
在浮点数中 的原因是:
参考解答
、、 的二进制展开都无限循环,存入时已经各自舍入;加法还要再舍入一次,结果与 的存储值不相等。这与溢出无关,也不是符号位造成的。
交互探索
0.1在32位里是什么样?
输入一个十进制数,拆开它的IEEE 754单精度符号、阶码和尾数。
正在准备演示…