2.3.2实例:符号求导
像之前一样,我们先假设已经有了一种表达代数表达式的方式,同时有相应的构造函数,选择函数和谓词。在此基础上根据求导法则完成符号求导的操作。做完这些后,我们再去实现代数表达式的定义与其支持的操作。完成这些还不够,使用的效果不如预期,这也是因为表达式是需要化简的。为了实现化简,我们对求和&&求乘积的方法进行修改。以上是整体的思路,接下来是代码的具体实现。
#lang sicp
(define (deriv exp var);;求导的方法,需要参数有表达式和变量
(cond ( (number? exp) 0);;如果表达式是一个数,求导为0
((variable? exp) ;;如果表达式是变量(不是数),分情况讨论
(if (same-variable? exp var) 1 0));;表达式是否与变量相同
((sum? exp);;如果为和式,分别求导再求和
(make-sum (deriv (addend exp) var)
(deriv (augend exp) var)
))
((product? exp);;如果为乘积,自己查数学求导方法
(make-sum (make-product
(multiplier exp)
(deriv (multiplicand exp) var))
(make-product
(multiplicand exp)
(deriv (multiplier exp) var))
))
(else
(error "error expression type" exp))
))
;;以上是求导程序。下面完善具体实现
(define (variable? exp);;判断是否是变量
(symbol? exp))
(define (same-variable? ex1 ex2);;判断两个变量是否相同
(and (variable? ex1) (variable? ex2) (eq? ex1 ex2)))
(define (make-sum a1 a2);;表达式求和
(cond ((=number? a1 0) a2)
((=number? a2 0) a1)
((and (number? a1) (number? a2)) (+ a1 a2))
(else (list '+ a1 a2))))
(define (=number? a int);;判断表达式是否等于一个数
(and (number? a) (= a int)))
(define (sum? exp);;是否为和式
(and (pair? exp) (eq? (car exp) '+)))
(define (addend exp);;取出第二个加数
(cadr exp))
(define (augend exp);;取出第一个加数
(caddr exp))
(define (product? exp);;判断乘式
(and (pair? exp) (eq? (car exp) '*)))
(define (make-product a1 a2);;表达式求乘积
(cond ((=number? a1 0) 0)
((=number? a2 0) 0)
((=number? a1 1) a2)
((=number? a2 1) a1)
((and (number? a1) (number? a2)) (* a1 a2))
(else (list '* a1 a2))))
(define (multiplier exp);;取出第一个乘式因子
(cadr exp))
(define (multiplicand exp);;取出第二个乘式因子
(caddr exp))
;;测试用例
(deriv '(+ x 3) 'x)
(deriv '(* (* x y) (+ x 3)) 'x)
2.3.2实例:符号求导
https://zzhygs.cn/index.php/archives/37/