跳到主内容
快讯直播
AI智模界
AI 词典

浮点数表示:0.1 + 0.2 为什么不等于 0.3

一句话定义

浮点数(floating point)是一套用「符号位 + 指数位 + 尾数位」三段式来近似表示实数的二进制编码规则;IEEE 754 是这套规则的国际标准,BF16(bfloat16)则是它针对 AI 计算推出的 16 位精简版。

原理:把科学计数法搬进芯片

人写数字习惯用科学计数法:1.23 × 10⁸。三个信息——正负号、小数点位置、有效数字。浮点数在二进制里做同一件事:

  • 符号位:正还是负
  • 指数位:小数点该往哪挪,决定能表示多大、多小的数
  • 尾数位:一共有几位有效数字,决定精度

关键约束是:二进制只能精确表示分母为 2 的幂的分数。0.5、0.25、0.125 都没问题,但 0.1 在二进制里是无限循环小数,只能被截断。所以计算机里存的从来不是 0.1,而是「离 0.1 最近的那个可表示的数」。两个这样的近似值相加,误差叠加,就得到了双精度下的 0.30000000000000004。这不是 bug,是编码方式的必然结果。

三种常见格式

格式总位数符号指数尾数大致十进制有效位
FP32321823约 7 位
FP16161510约 3 位
BF1616187约 2~3 位

BF16 的设计思路很直白:把 FP32 的 8 位指数原样保留,只把尾数从 23 位砍到 7 位。于是它的取值范围和 FP32 完全一样,只是变粗糙了。FP16 则相反,精度还行但指数位太少,容易溢出,训练时往往要做损失缩放(loss scaling)来兜底;BF16 不需要这套额外操作,这也是它在训练和推理里更省心的原因。

BF16 为什么够用

三点:一是动态范围没变,不会因为数值太大或太小而溢出;二是神经网络的权重、梯度、激活值本身是统计量,噪声很大,约 1% 的相对误差通常淹没在噪声里;三是矩阵乘法是访存密集型操作,数值位宽减半,显存占用和带宽压力也跟着减半,吞吐自然上去了。代价是累加等敏感环节容易掉精度,所以实践中常保留一份 FP32 的主副本来做累加和参数更新,具体怎么做以所用框架的官方文档为准。

精度损失从哪来

1. 表示误差:十进制小数转二进制时天生的截断。

2. 舍入误差:每次加减乘除都要把结果塞回可表示的网格,误差逐步累积。

3. 类型转换:FP32 转 BF16 要丢掉 16 位尾数。

4. 灾难性抵消:两个非常接近的大数相减,有效数字被大量抹掉,这是最凶险的一种。

对你意味着什么

普通职场人:涉及金额、对账的字段,永远别用浮点类型,改用整数(以「分」为单位)或十进制类型;看到 0.1 + 0.2 的结果时也不用惊讶。

AI 从业者:不要用严格相等去比较浮点数,改用误差容限;排查「训练好好的突然变 NaN」时,优先怀疑溢出、累加精度和抵消这三件事,而不是先怪数据。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。