我发现了一件有趣的事情。通过论证可能值得考虑,特别是在时间很重要的情况下。代码如下。
(define (collatz-num n)
(define (collatz-iter n m)
(cond
((= n 1)
m)
((even? n)
(collatz-iter (/ n 2) (+ m 1)))
(else
(collatz-iter (+ (* 3 n) 1) (+ m 1)))))
(collatz-iter n 1))
(define (collatz-iter n m)
(cond
((= n 1)
m)
((even? n)
(collatz-iter (/ n 2) (+ m 1)))
(else
(collatz-iter (+ (* 3 n) 1) (+ m 1)))))
(define (euler14 n limit)
(define (help-iter m len n limit)
(let ((collatz (collatz-iter n 1)))
(cond
((> n limit)
(list m len))
((> collatz len)
(help-iter n collatz (+ n 2) limit))
(else
(help-iter m len (+ n 2) limit)))))
(help-iter 0 0 n limit))
collatz-iter
> (time (euler14 1 1000000))
cpu time: 1596 real time: 1596 gc time: 0
collatz-num
> (time (euler14 1 1000000))
cpu time: 1787 real time: 1789 gc time: 0
我的问题:
在方案中传递参数的成本有多大
在函数euler14中,我让限制作为帮助者的参数,这样可以节省一些时间吗?正如我在某处看到的那样,自由变量将有成本。
也许我太吝啬了。
答案 0 :(得分:0)
再次。这是非常具体的实施!
我测试了你的代码,因为它确实消耗了内存并进行了大量的计算,我测试了这两个代码干扰第二个结果的顺序。我将每个文件中的两个测试分开并分别运行40次,并查看两者的平均运行时间。差异为num:1059.75,iter:1018.85。平均4%的差异,但在挑选两个样本时可能也是12%。我猜这个程序的运行时间平均可能超过4%,所以这两者之间的差异在一次运行中无关紧要。
您的代码中有一个额外的应用程序,以便检查参数对我进行此次测试的影响程度。在基本情况下使用参数是为了使Scheme不会优化它们:
(define (three-params x y z)
(if (zero? x)
(cons y z)
(three-params (- x 1) x x)))
(define (two-params x y)
(if (zero? x)
(cons x y)
(two-params (- x 1) x)))
(define (one-param x)
(if (zero? x)
(cons x x)
(one-param (- x 1))))
(define numtimes 100000000)
(time (one-param numtimes))
(time (two-params numtimes #f))
(time (three-params numtimes #f #f))
注释掉最后三行中的2行并制作3个文件。如果可以的话,编译它们。 几次运行的平均值。我选择了50,在Ikarus我得到以下平均值:
agvms diffms
one 402.4
two 417.82 15.42
three 433.14 15.32
two2 551.38 133.56 (with an extra addition compared to two)
只看50个结果,我看到时间在一,二,三之间重叠,但从统计上看,平均参数看起来是0,15ns。 if
,zero?
,-
和cons
以及gc
的费用要高得多,即使它们是原始的。您不应该关注额外的申请和额外的论点。有时,不同的实现会以不同的方式优化您的代码,因此从racket更改为ikarus,gambit或chicken可能会改善您的代码。