代码之家  ›  专栏  ›  技术社区  ›  Phil

两种组合函数的方法,效率有多不同?

  •  2
  • Phil  · 技术社区  · 16 年前

    让f将一个值转换为另一个值,然后我编写一个函数,重复转换n次。

    我提出了两种不同的方法:

    • 重复(f,4) 手段 f(f(f)(f(x)))
    • 快速供电方法,这意味着 问题只有一半大 只要n是偶数。所以 重复(f,4) 手段 g(x)=

    起初我以为第二种方法不会提高那么多效率。最终,我们仍然需要申请f n次,不是吗?在上述示例中, 没有任何进一步的简化,对吧?

    然而,当我尝试这些方法时,后一种方法明显更快。

    
    ;; computes the composite of two functions
    (define (compose f g)
      (lambda (x) (f (g x))))
    
    ;; identify function
    (define (id x) x)
    
    ;; repeats the application of a function, naive way
    (define (repeat1 f n)
      (define (iter k acc)
        (if (= k 0)
            acc
            (iter (- k 1) (compose f acc))))
      (iter n id))
    
    ;; repeats the application of a function, divide n conquer way
    (define (repeat2 f n)
      (define (iter f k acc)
        (cond ((= k 0) acc)
              ((even? k) (iter (compose f f) (/ k 2) acc))
              (else (iter f (- k 1) (compose f acc)))))
      (iter f n id))
    
    ;; increment function used for testing
    (define (inc x) (+ x 1))
    

    ((repeat2 inc 1000000)0) ((repeat1 inc 1000000)0)

    毕竟,应用程序必须重复n次,或者换一种说法, x(x+2) 正确的

    我正在运行DrScheme 4.2.1。

    非常感谢

    2 回复  |  直到 16 年前
        1
  •  3
  •   Eli Barzilay    16 年前

    inc 第二个只创建日志(N)闭包——如果闭包创建是大部分工作 然后你会看到性能上的巨大差异。

    1. 使用DrScheme time 测量速度的特殊表格。除了时间 它还将告诉您在GC中花费了多少时间。 您将看到第一个版本正在做一些GC工作,而第二个版本没有。

    2. 你的 股份有限公司 函数做得太少,以至于您只测量了循环开销。 例如,当我使用这个糟糕的版本时:

      (define (slow-inc x)
        (define (plus1 x)
          (/ (if (< (random 10) 5)
               (* (+ x 1) 2)
               (+ (* x 2) 2))
             2))
        (- (plus1 (plus1 (plus1 x))) 2))
      

      这两种用途之间的差异从约11倍降至1.6倍。

    3. (define (repeat3 f n)
        (lambda (x)
          (define (iter n x)
            (if (zero? n) x (iter (sub1 n) (f x))))
          (iter n x)))
      

      与第二个版本的速度相同。

        2
  •  1
  •   Community Mohan Dere    9 年前

    第一种方法基本上应用函数n次,因此它是O(n)。但第二种方法实际上并没有应用函数n次。每当称为repeat2时,只要n为偶数,它就会将n除以2。因此,在大多数情况下,问题的规模减半,而不仅仅是减少1。这给出了O(log(n))的总体运行时间。

    Martinho Fernandez exponentiation by squaring explains 非常清楚。