C++中float类型常量与变量的浮点表示为何存在差异?
核心原因
这个现象和「常量、变量的float表示差异」无关,本质是浮点字面量的默认类型规则+浮点数精度截断/隐式转换导致的:
- C++标准规定,不带任何后缀的浮点字面量(比如你代码里写的
0.3),默认类型是双精度double,不是单精度float。 - 你的变量
p是float类型,通常占4字节,有效精度约6~7位十进制数。执行p = 0.3时,等号右边是double类型的0.3近似值(double占8字节,有效精度约15~16位十进制数),赋值过程会发生精度截断,把双精度的0.3舍入成单精度能表示的最接近的近似值,存入p的内存空间。 - 执行判断
(p - 0.3) == 0时,等号右侧的0.3依然是double类型。计算减法前,编译器会把低精度的float值p隐式提升为double类型——这个提升只是把单精度的近似值补位到8字节长度,不会还原成最初赋值时的原生双精度0.3值。 - 此时参与减法运算的两个double值:一个是从单精度p转换来的近似值,一个是原生双精度0.3的近似值,二者存在微小的精度差,差值自然不等于0,因此触发else分支输出。
验证方法
如果你给所有0.3字面量加上f后缀,明确指定它是float类型的字面量,两边精度完全一致,就会得到你预期的输出:
#include <iostream> using namespace std; int main() { float p; p = 0.3f; if ((p - 0.3f) == 0) cout << "Of course, they are the same !!!\n"; else cout << "Not the same? Weird.....\n"; return 0; }
浮点数比较注意事项
不要直接用==判断两个浮点数是否相等。
二进制浮点数无法精确表示绝大多数十进制小数,不管float还是double,存储的都是目标值的近似值,直接判等很容易因为精度误差得到不符合预期的结果。正确的做法是判断两个值的差值绝对值,是否小于业务场景允许的极小误差阈值(通常叫epsilon),比如判断float值是否等于0.3可以写为:fabs(p - 0.3f) < 1e-6
内容的提问来源于stack exchange,提问作者J. H. Jeng
相关产品推荐
相关产品推荐

