我有两个逻辑上等效的函数:
long ipow1(int base, int exp) {
// HISTORICAL NOTE:
// This wasn't here in the original question, I edited it in,
if (exp == 0) return 1;
long result = 1;
while (exp > 1) {
if (exp & 1) result *= base;
exp >>= 1;
base *= base;
}
return result * base;
}
long ipow2(int base, int exp) {
long result = 1;
while (exp) {
if (exp & 1) result *= base;
exp >>= 1;
base *= base;
}
return result;
}
<小时/>
注意:
这些循环是等效的,因为在前一种情况下,我们返回 result * base
(处理 exp
已减少或已经减少的情况到1
),但在第二种情况下,我们返回结果
。
奇怪的是,-O3
和 -O0
ipow1
的性能均比 ipow2
好约 25%。这怎么可能?
我使用的是 Windows 7、x64、gcc 4.5.2,并使用 gcc ipow.c -O0 -std=c99
进行编译。
这是我的分析代码:
int main(int argc, char *argv[]) {
LARGE_INTEGER ticksPerSecond;
LARGE_INTEGER tick;
LARGE_INTEGER start_ticks, end_ticks, cputime;
double totaltime = 0;
int repetitions = 10000;
int rep = 0;
int nopti = 0;
for (rep = 0; rep < repetitions; rep++) {
if (!QueryPerformanceFrequency(&ticksPerSecond)) printf("\tno go QueryPerformance not present");
if (!QueryPerformanceCounter(&tick)) printf("no go counter not installed");
QueryPerformanceCounter(&start_ticks);
/* start real code */
for (int i = 0; i < 55; i++) {
for (int j = 0; j < 11; j++) {
nopti = ipow1(i, j); // or ipow2
}
}
/* end code */
QueryPerformanceCounter(&end_ticks);
cputime.QuadPart = end_ticks.QuadPart - start_ticks.QuadPart;
totaltime += (double)cputime.QuadPart / (double)ticksPerSecond.QuadPart;
}
printf("\tTotal elapsed CPU time: %.9f sec with %d repetitions - %ld:\n", totaltime, repetitions, nopti);
return 0;
}
最佳答案
不,确实,两者并不等同。 ipow2
当 ipow1
时返回正确的结果没有。
block 引用>附注我不在乎你留下多少评论来“解释”为什么它们是相同的,只需要一个反例就能反驳你的主张。
P.P.S。 -1,因为你对每个已经试图向你指出这一点的人表现出令人难以忍受的傲慢态度。
关于c - while (n > 1) 比 while (n) 快 25%?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7452028/