为什么C++中float类型变量赋值9.58后,判断f<9.58会返回true?
单精度float与默认双精度字面量比较出现意外真值的底层逻辑
你代码中f < 9.58判断返回true、程序输出T的结果,是C++语言规则与IEEE754浮点数硬件特性叠加的必然结果,并非代码语法逻辑错误:
核心触发逻辑
- 浮点字面量的默认类型规则
C++中书写的不带后缀的浮点数字面量,默认类型是double(双精度浮点数),和变量f的float(单精度浮点数)类型并不一致。也就是说判断条件里的9.58,在编译阶段就被按双精度规则处理,从根源上就不是和变量f同精度的数值。 - 二进制浮点的存储特性
9.58是十进制表示的无限循环二进制小数,不存在可以被单精度或双精度浮点数完全精确存储的9.58,所有存储的值都只是最接近真实9.58的近似值。 - 精度舍入的方向偏差
单精度浮点数仅能提供约6-7位十进制有效数字的精度,双精度可以提供约15-16位十进制有效数字的精度。当把默认双精度精度的9.58赋值给单精度变量f时,会因为单精度的表示容量限制,将数值舍入到最近的、单精度可以承载的浮点数点上。
实际编译运行时,两个值的真实近似为:- 单精度变量
f存储的舍入值:约9.5799999237... - 判断条件中双精度字面量
9.58的存储值:约9.5800000000...
两者比较时,单精度存储的舍入值刚好小于双精度精度的字面量值,因此判断条件成立。
- 单精度变量
常见修正方案
- 给判断条件中的浮点字面量加
f后缀,强制将其转为和变量f一致的单精度类型。此时两边是同一次舍入得到的相同值,判断自然会输出F,示例写法为:if(f < 9.58f) - 对精度敏感的业务场景,不要直接用等于、小于这类精确比较符判断浮点数,需根据业务容忍度设置合理的误差范围(比如判断两个数的差值绝对值小于1e-6视为相等),从根源上规避二进制浮点精度带来的逻辑偏差。
内容的提问来源于stack exchange,提问作者Bikramjit Das
相关产品推荐
相关产品推荐

