为何同类型的两段C语言程序输出结果存在差异?
为什么两个看似相似的C程序输出结果不同?
这事儿本质上是浮点数的精度限制和类型转换时的舍入规则搞的鬼,咱们一步步拆解清楚:
先搞懂代码里的类型转换细节
首先看你的两段代码:
- 你写的
0.7d和0.8d是double类型的字面量(d后缀明确指定为双精度浮点数,就算不加d,0.7默认也是double类型)。 - 当把double值赋值给
float a时,因为float是单精度浮点数(只有24位有效二进制位),而double有53位有效位,精度差了一倍多,所以必须把double的近似值舍入到最接近的float值——这一步就会产生无法避免的误差。
0.7和0.8的舍入方向为啥不一样?
十进制的0.7和0.8都无法用二进制浮点数精确表示,它们都是无限循环的二进制小数。这就导致:
- 对于0.7来说,它的double近似值,在舍入到float精度时,会被向下舍入——最终存在
a里的float值,比真实的0.7(或者说double版本的0.7)要小一点点。 - 对于0.8来说,它的double近似值舍入到float精度时,会被向上舍入——存在
a里的float值,比真实的0.8(double版本的0.8)要大一点点。
比较时的类型放大是关键
当执行a < 0.7这个判断时,C语言会自动做类型提升:把float类型的a转换成double类型(只是扩展精度,不会改变a原本的近似值)。
- 第一个程序里,提升后的double值(来自float的0.7)比原来的double 0.7小,所以
a < 0.7成立,输出C。 - 第二个程序里,提升后的double值(来自float的0.8)比原来的double 0.8大,所以
a < 0.8不成立,输出C++。
验证小技巧
如果把比较的右侧也转换成float类型,比如写成a < (float)0.7,那两段程序都会输出C++——因为此时a和(float)0.7是完全相等的(都是经过舍入后的float近似值)。
内容的提问来源于stack exchange,提问作者a srinivasa reddy
相关产品推荐
相关产品推荐

