初始化的浮点变量与零比较的行为:是编译器依赖还是标准规定?
嘿,这个问题问得挺戳点的,刚好理清了浮点数比较里的一个常见误区——不是所有浮点比较都有“玄学”,得看具体场景!先给你拍板:你代码里的这些和零比较相等的行为,是C++标准明确规定的,完全不是编译器依赖的。
咱们逐个拆解你代码里的几种情况:
第一种场景:
double d = 0;
把整数0赋值给double变量d时,根据C++标准,只要这个整数能被目标浮点类型精准表示(0肯定没问题,所有二进制浮点格式都能完美存储0),转换结果就是精确的浮点值。所以d的实际值就是精确的double类型0.0,这时候用d == 0或者d == 0.0f比较,结果必然是true:0会被自动提升为double类型和d对比,0.0f转换为double也是精确的0.0,所以相等是板上钉钉的,和编译器半毛钱关系都没有。第二种场景:
d = 2.0f - 2.0f;
两个float类型的2.0f相减,结果是精确的float类型0.0f,再赋值给double类型的d。标准明确规定,float到double的转换是完全精确的(因为double的精度更高,能覆盖float的所有可表示值),所以d还是精确的0.0,和零比较自然还是相等,这也是标准拍板的结果。第三种场景:
d = 2.0f - 2.0f + 1.0e-320;
这里的关键是1.0e-320这个数,它比float能表示的最小非零值还要小得多(float的最小正规格化值大概是1.175e-38,非规格化值也到不了这么小)。不过注意,1.0e-320是double类型的常量(没有f后缀),所以2.0f - 2.0f会先被提升为double类型的0.0,再加上这个极小的double值,结果就是这个非零的小数值(double的非规格化范围能容纳它)。这时候d不等于0,也是标准规定的——因为浮点运算的舍入、转换规则都是标准明确的,只要编译器遵循标准,结果就一致。
最后补一句大家常说的“别用比浮点数”的前提:那是针对经过复杂计算得到的浮点数,多次运算可能引入微小精度误差,导致理论上相等的值实际不等。但如果是直接初始化、或者精确值的简单运算(比如相同值相减),结果是精确的,这时候用完全没问题,是标准保证的。
内容来源于stack exchange




