首页 > 解决方案 > 方案 - 使用表格的导数

问题描述

我正在尝试使用下面的代码获得方案中的导数。谁能告诉我哪里出错了?我一直试图弄清楚一段时间。

(define d3
  (λ (e)
    (cond ((number? e) 0)
      ((equal? e 'x) 1)
      (else
       ;; We handle only BINARY ops here, and only + and *
       (let ((op (car e)) (args (cdr e)))
         (apply (lookup op d-op-table) args))))))


(define d-op-table
  (list(list '+ (λ (u v) (+ (d3 u) (d3 v))))
       (list '+ (λ (u1 v1)
             (list '(* u1 (d v1)))(list '(* (d u1) v1))))))

(define lookup
  (λ (op table)
    (if (equal? op (caar table))
    (cadar table)
    (lookup op (cdr table)))))

当我运行该函数时,我收到以下错误。我输入,(d3'(* 2 x))。

    caar: contract violation
  expected: (cons/c pair? any/c)
  given: '()

标签: schemelispracket

解决方案


查找表不正确,有时您评估表达式,但其他人您只是引用它们,而不评估它们。例如,'(* u1 (d v1))将只计算为'(* u1 (d v1)),实际上并未计算导数!乘法的情况看起来特别糟糕,它甚至没有正确的搜索键*

这更接近您的意图,请注意您需要更多的工作来实际检测哪些表达式可以简化 - 例如:(* 0 x)is 0,但这应该足以让您开始:

(define d-op-table
  (list (list '+ (λ (u v) (list '+ (d3 u) (d3 v))))
        (list '* (λ (u v)
                   (list '+
                         (list '* u (d3 v))
                         (list '* (d3 u) v))))))

现在您的示例有效:

(d3 '(* 2 x))
=> '(+ (* 2 1) (* 0 x))

如果你想写一个真正有用的微分程序,最好看看SICP


推荐阅读