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.
当b
在float
算术中乘以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 标准允许使用额外的精度,但通常您会在这里看到相同的结果。
我有这样一个程序
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.
当b
在float
算术中乘以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 标准允许使用额外的精度,但通常您会在这里看到相同的结果。