浮点数什么时候会发生舍入
一、核心原理
计算机二进制浮点数(IEEE 754)存储空间有限,实数无法精确表示、运算后有效位超出存储位数时,必须舍入。
二、会触发舍入的 4 大类场景
1. 十进制小数转二进制存储(最常见)
很多十进制小数无法用有限二进制小数表达,存入 float/double 时直接舍入。 例:
0.1二进制是无限循环小数,存进 double 会截断舍入;0.2、0.3、0.6同理。 验证:0.1 + 0.2 != 0.3,根源就是存储时舍入。
2. 算术运算后有效位数超标
浮点数有固定尾数长度(float23 位、double52 位),加减乘除后有效数字超过尾数容量,必须舍入:
- 乘法:两个 n 位尾数相乘,结果是 2n 位,超出存储位,强制舍入; 例:
0.1 * 0.3 - 除法:大概率产生无限二进制小数,截断舍入;
- 加法 / 减法:
- 大数加小数:小数低位被丢弃,舍入; 例:
1e20 + 0.1,0.1 直接丢失,无误差但本质是舍入丢弃; - 相近数相减(有效数字抵消):剩余有效位变少,低位舍入。
- 大数加小数:小数低位被丢弃,舍入; 例:
3. 数值超出 / 低于表示范围(溢出、下溢)
- 上溢:运算结果超过浮点数最大值 → 舍入为
+Inf / -Inf; - 下溢:结果极小,小于最小规格化浮点数,进入非规格化区间,尾数低位被迫舍入,精度丢失。
4. 类型强制转换、精度截断
高精度浮点数转低精度,位数减少,直接舍入:
- double → float:52 位尾数压缩到 23 位,多余低位舍入;
- float → 整数:小数部分直接舍入(按语言规则,四舍五入 / 向零截断);
- 高精度十进制(Python decimal)转普通 float。
三、补充:不会舍入的情况
- 十进制小数能转有限二进制小数:0.5、0.25、0.75、1.25 等;
- 整数范围不超过尾数全部精度:double 可以无损保存 ±2⁵³ 以内所有整数,运算无舍入;
- 运算结果尾数位数刚好匹配存储宽度。
四、IEEE 754 默认舍入规则
默认:四舍六入五成双(银行家舍入)不是简单四舍五入,减少累积误差。
总结一句话
只要数字无法用有限二进制尾数完整存放,无论是存储、计算、类型转换,都会触发浮点数舍入。