Пусть f преобразует одно значение в другое, тогда я пишу функцию, которая повторяет преобразование n раз.
Я придумал два разных способа:
- Один очевидный способ
буквально применяет функцию п
раз, поэтому повтор (f, 4) означает x →
е (е (е (е (х))))
- Другой путь вдохновлен
быстрый способ питания, что означает
разделив проблему на две части
проблемы вдвое меньше
всякий раз, когда п четный. Итак, повтор (f, 4)
означает x → g (g (x)) , где g (x) =
е (е (х))
Сначала я подумал, что второй метод не так сильно повысит эффективность. В конце концов, мы все равно должны были бы подать заявку n раз, не так ли? В приведенном выше примере g будет по-прежнему переводиться в f o f без дальнейшего упрощения, верно?
Однако, когда я опробовал методы, последний метод был заметен быстрее.
;; 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 + 1) +1) не может быть автоматически уменьшено до x → (x +2) , верно?
Я использую DrScheme 4.2.1.
Большое спасибо.