【问题标题】:Different rounding between assignment and printfassignment 和 printf 之间的不同舍入
【发布时间】:2013-05-13 04:32:54
【问题描述】:

我有一个包含两个 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 写入的值不同(相差 0.000001,当打印 6 个小数位时)。

除法前的值为:

num = 10201 
other_num = 2282

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

以下是小数点后 15 位的数字:

4.470201577563540
4.470201492309570

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

为什么这个预期不正确?

谢谢。

【问题讨论】:

  • 它们在我刚刚进行的快速测试中匹配。 numother_num 的值是多少?您使用的是什么环境(主机架构、编译器版本等)?
  • 我编辑了问题并提供了数字。谢谢。

标签: c floating-point


【解决方案1】:

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

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

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

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

【讨论】:

  • 谢谢。这很有趣。我尝试将 r 变量声明为双精度,并且两个打印都开始输出与 printf 调用相同的值。这与你写的一致。
【解决方案2】:

点是程序执行过程中表达式结果的实际位置。如果编译器认为这种优化在特定情况下是可能的,C 值可以存在于内存(包括缓存)或仅存在于寄存器中。

在第一个 printf 中,表达式结果存储在寄存器中,因为该值仅在同一 C 指令中使用,因此编译器(正确地)认为将其存储在易失性较小的地方是没有用的;因此,值会根据架构存储为 double 或 long double。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-14
    • 2017-12-14
    • 1970-01-01
    • 2016-01-07
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多