在Common Lisp中更改为+

时间:2014-11-09 00:23:16

标签: function lisp common-lisp

有没有办法将-(减号)函数更改为+(加号)函数?

我的作业是在Macluaurin系列上实现罪计算

sin(x) = x-(x^3/3!)+(x^5/5!) -(x^7/7!)+(x^9/9!)-...

每篇文章都有不同的标志。这是我的Lisp代码

(defun sinMac (x series n plusminus)
  (cond ((= series 0) 0)
        (t (funcall plusminus
                    (/ (power x n) (factorial n))
                    (sinMac x (- series 1) (+ n 2) plusminus)))))

是否可以更改plusminus以兑换标志?如果我得到'+函数发送'-到下一个递归调用。通过该电话(获得'-),我致电'+,依此类推......

3 个答案:

答案 0 :(得分:4)

你可以用圆形列表来做。像这样:

(defun sin-mac (x series n plus-minus)
  (cond ((zerop series) 0)
        (t (funcall (car plus-minus)
                    (/ (power x n) (factorial n))
                    (sin-mac x (1- series) (+ n 2) (cdr plus-minus))))))

(sin-mac x series 1 '#0=(+ - . #0#))

甚至更好,使用labels包装初始参数:

(defun sin-mac (x series)
  (labels ((recur (series n plus-minus)
             (cond ((zerop series) 0)
                   (t (funcall (car plus-minus)
                               (/ (power x n) (factorial n))
                               (recur (1- series) (+ n 2) (cdr plus-minus)))))))
    (recur series 1 '#0=(+ - . #0#))))

答案 1 :(得分:3)

如果函数是符号,这很容易:

(defun next-function (function)
  (ecase function
    (+ '-)
    (- '+)))

(defun sinMac (x series n plusminus)
  (cond ((= series 0) 0)
        (t (funcall plusminus
                    (/ (power x n) (factorial n))
                    (sinMac x
                            (- series 1)
                            (+ n 2)
                            (next-function plusminus))))))

答案 2 :(得分:1)

我不会交换功能而只是交换标志。使用循环对我来说似乎也更清楚(尽管仍有很多优化机会,但最有可能更有效率):

(defun maclaurin-sinus (x n)
  "Calculates the sinus of x by the Maclaurin series of n elements."
  (loop :for i :below n
    :for sign := 1 :then (- sign)
    :sum (let ((f (1+ (* 2 i))))
           (* sign
              (/ (expt x f)
                 (factorial f))))))

一些优化使这大约快10倍(使用 n = 5 进行测试):

(defun maclaurin-sinus-optimized (x n)
  "Calculates the sinus of x by the Maclaurin series of n elements."
  (declare (integer n))
  (loop :repeat n
    :for j :from 0 :by 2
    :for k :from 1 :by 2
    :for sign := 1 :then (- sign)
    :for e := x :then (* e x x)
    :for f := 1 :then (* f j k)
    :sum (/ e f sign)))