赋值和printf之间的不同舍入

时间:2013-05-17 22:12:35

标签: c floating-point

我有一个包含两个int类型变量的程序。

int num;
int other_num;

/* change the values of num and other_num with conditional increments */

printf ("result = %f\n", (float) num / other_num);

float r = (float) num / other_num;
printf ("result = %f\n", r);

第一个printf中写入的值与第二个printf写入的值不同(以小数点后6位打印时为0.000001)。

在除法之前,值为:

num = 10201 
other_num = 2282

我已将结果数字打印到小数点后15位。这些数字在小数点后7位有所不同,这解释了第6位的差异。

以下是15位小数的数字:

4.470201577563540
4.470201492309570

我知道浮点舍入问题,但我期望在赋值和printf参数中执行时计算结果是相同的。

为什么这种期望不正确?

感谢。

2 个答案:

答案 0 :(得分:8)

可能是因为FLT_EVAL_METHOD在你的系统上不是0。

在第一种情况下,表达式(float) num / other_num具有名义类型float,但可能以更高的精度进行评估(如果您使用的是x86,可能是long double)。然后转换为double以传递给printf

在第二种情况下,将结果分配给类型为float的变量,这会强制丢弃多余的精度。然后,float在传递给double后会升级为printf

当然没有实际数字,这只是猜测。如果您想要更明确的答案,请提供有关您问题的完整详细信息。

答案 1 :(得分:1)

该点是程序执行期间表达式结果的实际位置。如果编译器决定在特定情况下可以进行这种优化,则C值可以存在于内存(包括高速缓存)上,也可以只存在于寄存器上。

在第一个printf中,表达式结果存储在一个寄存器中,因为该值只是在同一个C指令中使用,所以编译器认为(正确地)将它存储在不太易变的地方是没用的;因此,根据体系结构,该值将存储为double或long double。

在第二种情况下,编译器没有执行这样的优化:值存储在堆栈中的变量中,该变量是内存,而不是寄存器;因此,相同的值在第23位有效位被截断。

更多示例是provided by streflop及其文档。