I can't explain the behaviour of the following program (compiled with gcc on mingw 32 bits). I'm aware of the possible precision loss when implicitly converting from double to int, but I would expect the two cases to give the same output since it is doing the exact same operations. Why are the two outputs different?
我无法解释下一个程序的行为(编译与gcc在mingw32位上编译)。当隐式地从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
1 个解决方案
#1
14
With pow(100, 0)
pow(100, 1)
and pow(100, 2)
the compiler replaces the function calls with constants (1, 100, 10000
), but with pow(100, i)
it has to actually call the function at runtime (because of the variable i
being passed as argument), resulting with two results of pow
in the form 0.99999999
and 99.999999
instead of 1
and 100
(or any 2 of the 3). When truncating to int after the multiply you "lose" two units.
战俘(100,0)战俘(100 1)和战俘(100 2)编译器取代了函数调用与常量(100,10000),但与战俘(100年,我)来调用该函数在运行时(因为我被作为参数传递的变量),造成两个结果的战俘在0.99999999和99.999999,而不是1和100(或任何2的3)。当删除int后把你“失去”两个单位。
This is another example of why converting to int
from double
is just pure evil: very hard to find subtle bugs in your program (not compiler bugs).
这是为什么从double转换为int是完全邪恶的另一个例子:很难在程序中找到细微的错误(不是编译器错误)。
Btw, I am surprised that the compiler with O2
didn't unroll the loop, propagate the constants and reach the same optimization (replacing the function call with constant results).
顺便说一句,我很惊讶于使用O2的编译器没有展开循环、传播常量并达到相同的优化(用常量结果替换函数调用)。
Btw2 Scratch that, I am surprised that the compiler didn't just replace all you code with only two calls to printf
.
Btw2 Scratch,我很惊讶编译器并没有仅仅用两个调用printf来替换所有的代码。
#1
14
With pow(100, 0)
pow(100, 1)
and pow(100, 2)
the compiler replaces the function calls with constants (1, 100, 10000
), but with pow(100, i)
it has to actually call the function at runtime (because of the variable i
being passed as argument), resulting with two results of pow
in the form 0.99999999
and 99.999999
instead of 1
and 100
(or any 2 of the 3). When truncating to int after the multiply you "lose" two units.
战俘(100,0)战俘(100 1)和战俘(100 2)编译器取代了函数调用与常量(100,10000),但与战俘(100年,我)来调用该函数在运行时(因为我被作为参数传递的变量),造成两个结果的战俘在0.99999999和99.999999,而不是1和100(或任何2的3)。当删除int后把你“失去”两个单位。
This is another example of why converting to int
from double
is just pure evil: very hard to find subtle bugs in your program (not compiler bugs).
这是为什么从double转换为int是完全邪恶的另一个例子:很难在程序中找到细微的错误(不是编译器错误)。
Btw, I am surprised that the compiler with O2
didn't unroll the loop, propagate the constants and reach the same optimization (replacing the function call with constant results).
顺便说一句,我很惊讶于使用O2的编译器没有展开循环、传播常量并达到相同的优化(用常量结果替换函数调用)。
Btw2 Scratch that, I am surprised that the compiler didn't just replace all you code with only two calls to printf
.
Btw2 Scratch,我很惊讶编译器并没有仅仅用两个调用printf来替换所有的代码。