我无法解释以下程序的行为(在mingw 32位上使用gcc编译)。我意识到隐式从double转换为int时可能出现的精度损失,但我希望这两种情况能够提供相同的输出,因为它执行完全相同的操作。为什么两个输出不同?
#include <stdio.h>
#include <math.h>
int main()
{
int table[3] = {2, 3, 4};
int i, N;
N = 0;
N += table[0] * pow(100, 0);
N += table[1] * pow(100, 1);
N += table[2] * pow(100, 2);
printf("%d\n", N);
N = 0;
for(i = 0; i < 3; i++)
N += table[i] * pow(100, i);
printf("%d\n", N);
return 0;
}
//output:
40302
40300
答案 0 :(得分:14)
使用pow(100, 0)
pow(100, 1)
和pow(100, 2)
编译器用常量(1, 100, 10000
)替换函数调用,但是使用pow(100, i)
它必须实际调用函数在运行时(因为变量i
作为参数传递),导致pow
和0.99999999
而不是99.999999
形式的1
的两个结果, 100
(或3中的任何2个)。在乘法后截断到int时,你会“失去”两个单位。
这是为什么从int
转换为double
只是纯粹恶意的另一个例子:很难在程序中找到微妙的错误(不是编译器错误)。< / p>
顺便说一下,我很惊讶带O2
的编译器没有展开循环,传播常量并达到相同的优化(用常量结果替换函数调用)。
Btw2 Scratch,我很惊讶编译器不只是用printf
的两次调用来替换你所有的代码。