哪种实现更快(理论上) -
long int total=0;
for(int n=1;n<=200000;)`
{
total=total + n*(++n);
}
或
long int total=0,sum=0;
for(int n=1;n<=200000;n++)`
{
sum =sum+2*n;
total=total + sum;
}
或者没有任何区别?
答案 0 :(得分:3)
您需要做的是明确写下您要比较的两个程序。我想我知道你的意思,但是如果你明确地写它就会是明确的。
假设我猜对你的意思是正确的,渐近时间复杂度对这个问题毫无意义,因为没有自由变量。 n
被“绑定”到循环中。如果您将200000
替换为M
,那么谈论时间复杂度会有所帮助。
你没写的两个节目中的哪一个在绝对意义上更快的问题也是一个框架不好的问题,因为答案很可能取决于背景,正如Mark Dickinson指出的那样。如果我的猜测是正确的程序是什么样的,那么算术运算的数量似乎大致相同。这可能意味着程序将在大约相同的时间内运行,或者可能不运行。我的猜测是时间差异难以察觉,但为什么不尝试呢?
最后,如果您要使用捷径2(1)+2(2)+...+2(n)=n(n+1)
,那么为什么不进一步使用捷径来表示1(2)+2(3)+...+n(n+1)
的总和?我们有
n(n+1) = (1/3)((n+1)^3 - n^3) - (1/3)
所以
1(2)+2(3)+...+n(n+1)
= (1/3)(2^3-1^3) - (1/3) + (1/3)(3^3-2^3) - (1/3) + ... + (1/3)((n+1)^3-n^3) - (1/3)
= ((n+1)^3 - n - 1)/3
这个系列是“伸缩式”的,所以中间的所有立方术语都取消了。结果表达式可以在5个算术运算中进行评估。
如果您在上面替换n = 200000,您会看到int total
将溢出32位int
类型。这是你的意图吗?
<强>更新强>
我在我的系统上试过它(MacBook Air / Yosemite)。我比较的程序是
#include <stdio.h>
int main() {
long int total;
for (int trial=0; trial<1000; ++trial) {
total = 0;
for (int i=1; i<=200000; ++i) {
total = total + i*(i+1);
}
}
printf("answer is %ld", total);
return 0;
}
和
#include <stdio.h>
int main() {
long int total;
int sum;
for (int trial=0; trial<1000; ++trial) {
total = 0;
sum = 0;
for (int i=1; i<=200000; ++i) {
sum = sum + 2*i;
total = total + sum;
}
}
printf("answer is %ld", total);
return 0;
}
我用gcc -O
编译了两个,然后在unix time
命令下运行它们。明显的赢家(在我的系统上,具有特定的架构,以及我做出的选择)是第一个程序。它需要大约160毫秒,而第二个需要大约240毫秒。第一个在第二个时间的2/3运行。我对架构的了解不足以推测出差异的原因。
请注意,程序total = total + i*(i++);
中的行不正确。这会计算i*i
然后递增i
。此外,该行和改进的total = total + i*(++i)
都会生成警告。
一些风格问题:我使用i
而不是n
作为循环索引,因此人们不会对n
的含义感到困惑。我习惯使用++x
来增加x而不是x++
,这可能会使旧的x
成为不必要的临时副本。
答案 1 :(得分:-2)
好吧,如果你在谈论算法,那么第一次操作的复杂性高于第二次操作。 第一次操作的复杂性是O(1),而在第二种情况下,它将是O(n)。 因此,当您的输入数量增加时,可能第一个将比第二个花费更少的时间。 延迟与执行操作所需的机器指令成正比。