唯一公平的比较是在普通硬件上的最短完成时间。完成一个程序的时间完全取决于硬件,否则花钱购买更强大的机器又有什么意义呢?
最接近可重现结果的是报告相对速度,例如,提供示例程序并根据用户程序在 50% 的时间内运行的情况进行报告。在一台 PC 上速度是两倍的程序在另一台 PC 上的速度可能是两倍。
在 uni,我们会提交会违反“秘密”输入的作业,但是我们可以多次提交以纠正错误。我的第一次提交根本不起作用,但会记录所有输入。;)
编辑:更长的答案。
考虑以下程序
public class FibMain {
public static void main(String... args) {
{
long start = System.nanoTime();
System.out.println(iteration_fib(Integer.parseInt(args[0])));
long time = System.nanoTime() - start;
System.out.printf("Iteration took %,d us%n", time / 1000);
}
{
long start = System.nanoTime();
System.out.println(recursive_fib(Integer.parseInt(args[0])));
long time = System.nanoTime() - start;
System.out.printf("Recursion took %,d us%n", time / 1000);
}
}
public static long iteration_fib(int n) {
long t1 = 1;
long t2 = 1;
while (n-- > 2) {
long t = t2;
t2 += t1;
t1 = t;
}
return t2;
}
public static long recursive_fib(int n) {
if (n <= 2) return 1;
return recursive_fib(n - 1) + recursive_fib(n - 2);
}
}
如果你用 javap -c 查看生成的字节码,你会看到
public static long iteration_fib(int);
Code:
0: lconst_1
1: lstore_1
2: lconst_1
3: lstore_3
4: iload_0
5: iinc 0, -1
8: iconst_2
9: if_icmple 25
12: lload_3
13: lstore 5
15: lload_3
16: lload_1
17: ladd
18: lstore_3
19: lload 5
21: lstore_1
22: goto 4
25: lload_3
26: lreturn
public static long recursive_fib(int);
Code:
0: iload_0
1: iconst_2
2: if_icmpgt 7
5: lconst_1
6: lreturn
7: iload_0
8: iconst_1
9: isub
10: invokestatic #13; //Method recursive_fib:(I)J
13: iload_0
14: iconst_2
15: isub
16: invokestatic #13; //Method recursive_fib:(I)J
19: ladd
20: lreturn
所以第一个例子比第二个例子长,所以你可能怀疑第一个例子需要更长的时间。但是,对于“n”是一个有趣的大小的情况,您将是不正确的。
我在我的机器上运行了 FibMain 44 并得到了以下结果。
701408733
Iteration took 495 us
701408733
Recursion took 19,174,036 us
这是因为执行迭代所花费的时间与 n (在本例中为 44)成正比,它线性增长,但递归所花费的时间与结果成正比(在本例中为 701408733)并且呈指数增长。
如果你尝试 50 作为输入,第一个在眨眼间完成,第二个需要很长时间,我已经厌倦了等待。