【问题标题】:change - to + in Common Lisp在 Common Lisp 中将 - 更改为 +
【发布时间】:2014-11-09 00:23:15
【问题描述】:

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

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

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 更改为交换符号?如果我得到'+ 函数发送'- 到下一个递归调用。从那个电话(得到'-)我打电话给'+等等......

【问题讨论】:

    标签: function lisp common-lisp


    【解决方案1】:

    你可以用一个循环列表来做到这一点。像这样:

    (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#))))
    

    【讨论】:

      【解决方案2】:

      如果函数是符号,这很简单:

      (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))))))
      

      【讨论】:

        【解决方案3】:

        我不会交换函数,而只是交换符号。对此使用循环对我来说似乎更清楚(并且很可能更有效,尽管仍有很多优化机会):

        (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)))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-03
          • 2015-09-11
          • 1970-01-01
          • 2014-02-20
          • 1970-01-01
          • 2018-11-11
          • 2019-04-18
          • 1970-01-01
          相关资源
          最近更新 更多