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, и цикл был бы выполнен.
ОтветитьУдалить