C语言中使用变量和使用直接数的区别

Differences between using variable and using direct number in C language

我有这样一个程序

int a = 100;
float b = 1.05;
printf("%f\n", a * b);
printf("%f\n", 100 * 1.05);

其输出如下所示:

104.999992
105.000000

我知道“104.99992”是由于浮点精度问题。但为什么使用直接数字不会导致准确性损失?

a * b 使用 float 算术。 100 * 1.05 使用 double 算术。

您的 C 实现可能对 double 使用 IEEE-754 binary64,对 float 使用 binary32。

1.05 是一个 double 常量。源文本中的十进制数字 1.05 被转换为最接近的可表示 double 值,即 4728779608739021•2−52 = 1.0500000000000000444089209850062616169452667236328125.

float b = 1.05; 将该值转换为 float。转换的结果是最接近的可表示的float值,即4728779393990656•2−52 = 4404019•2−22 = 1.0499999523162841796875.

bfloat算术中乘以100时,结果是最接近实数算术结果的可表示float值。是13762559•2−17 = 104.99999237060546875.

打印小数点后六位时,结果为“104.999992”。

100 * 1.05中,只用到double算术;没有 float 个值。当 double 1.0500000000000000444089209850062616169452667236328125 乘以 100 时,结果是最接近实数运算结果的 double。就是105•20 = 105,打印小数点后六位,结果当然是“105.000000”。

总结:浮点运算一般存在舍入误差。在 float 算法中,当打印的数字多于几个数字时,它们很容易看到。在这个使用 double 算法的示例中,舍入误差恰好被抵消——最接近的 double 1.05 略高于 1.05,因此转换中的舍入向上舍入。然后,当它乘以 100 时,最接近实数运算结果的 double 略低于它,因此乘法中的舍入向下舍入。这些有效地取消,产生 105.

如果执行printf("%f\n", 100*1.05f);1.05f将直接转换为float而不是double,并且乘法将与[=11=一起完成] arithmetic,1 你会看到与 a * b.

相同的结果

脚注

1 C 标准允许使用额外的精度,但通常您会在这里看到相同的结果。