1. Вычисления Факториала в цикле
;; Рекурсивное вычисление факториала
(defun fact (n)
(if (= 1 n)
1
(* n (fact (- n 1)))))
;; Рекурсивное вычисление факториала
;; с использованием хвостовой рекурсии
(defun fact2 (counter &optional (val 1))
(if (= counter 0)
val
(fact2 (- counter 1) (* val counter))))
;; Вычисление факториала с помощью цикла do
(defun fact3 (n)
(let ((f 1))
(do ((i 2 (+ i 1)))
((> i n) f)
(setf f (* f i)))))
;;; Сравниваем результат вычислений и
;;; ресурсоёмкость трёх функций
(= (time (fact 20000))
(time (fact2 20000))
(time (fact3 20000)))Результат выполнения:Evaluation took: 0.426 seconds of real time 0.420026 seconds of total run time (0.400025 user, 0.020001 system) [ Run times consist of 0.064 seconds GC time, and 0.357 seconds non-GC time. ] 98.59% CPU 855,372,860 processor cycles 303,248,336 bytes consed Evaluation took: 0.437 seconds of real time 0.436027 seconds of total run time (0.436027 user, 0.000000 system) [ Run times consist of 0.044 seconds GC time, and 0.393 seconds non-GC time. ] 99.77% CPU 877,747,980 processor cycles 339,314,808 bytes consed Evaluation took: 0.402 seconds of real time 0.400025 seconds of total run time (0.380023 user, 0.020002 system) [ Run times consist of 0.076 seconds GC time, and 0.325 seconds non-GC time. ] 99.50% CPU 807,685,920 processor cycles 303,254,160 bytes consed TВариант вычисления при помощи цикла самый быстрый, на втором месте идёт рекурсивная функция, на третьем - рекурсивная с хвостовой рекурсией.
2. Вычисление чисел Фибоначчи
;; Вычисление чисел Фибоначчи рекурсией
(defun fib (num &key (a 1) (b 1))
(if (= num 1)
a
(fib (- num 1) :a b :b (+ a b))))
;; Вычисление чисел Фибоначчи с использованием цикла do
(defun fib2 (n &key (a 1) (b 1))
(cond ((= n 1) a)
((= n 2) b)
(T (do ((i 3 (+ i 1)))
((= i n) (+ a b))
(shiftf a b b (+ a b))))))
;;; Сравниваем результат вычислений и
;;; ресурсоёмкость функций
(= (time (fib 20000))
(time (fib2 20000)))Результат выполнения программы:Evaluation took: 0.030 seconds of real time 0.032002 seconds of total run time (0.032002 user, 0.000000 system) [ Run times consist of 0.012 seconds GC time, and 0.021 seconds non-GC time. ] 106.67% CPU 60,564,250 processor cycles 17,588,392 bytes consed Evaluation took: 0.025 seconds of real time 0.024001 seconds of total run time (0.024001 user, 0.000000 system) [ Run times consist of 0.004 seconds GC time, and 0.021 seconds non-GC time. ] 96.00% CPU 48,908,280 processor cycles 17,597,480 bytes consed TВычисление с помощью циклов оказалось быстрее. Хотя, если производительность - не главное, то я выбрал бы рекурсивный вариант - он легче читается и красивее выглядит.

Здравствуйте!
ОтветитьУдалить(defun fib2 (n &key (a 1) (b 1))
(cond ((= n 1) a)
((= n 2) b)
(T (do ((i 3 (+ i 1)))
((= i n) (+ a b))
(shiftf a b b (+ a b))))))
можете объяснить последнюю строчку и что значит T перед циклом do?
Оператор cond принимает список условий и действий, которые нужно выполнить, если соответствующее условие истинно. Если n=1, то возвращается a. Если n=2, то возвращается b. Если ни то ни другое не сработало, то выполняется цикл. T - это истина. Вместо T можно было написать что-то вроде (= n n) и это выражение тоже вычилилось бы в T, и цикл был бы выполнен.
ОтветитьУдалить