シンボルを使って式の微分。
前準備
(define (deriv exp var) (cond ((number? exp) 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 (deriv (multiplier exp) var) (multiplicand exp)))) (else (error "unknown expression type -- DERIV" exp)))) (define (variable? x) (symbol? x)) (define (same-variable? v1 v2) (and (variable? v1) (variable? v2) (eq? v1 v2))) ; 項の和 (define (sum? x) (and (pair? x) (eq? (car x) '+))) (define (addend s) (cadr s)) (define (augend s) (caddr s)) (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 (product? x) (and (pair? x) (eq? (car x) '*))) (define (multiplier p) (cadr p)) (define (multiplicand p) (caddr p)) (define (make-product m1 m2) (cond ((or (=number? m1 0) (=number? m2 0)) 0) ((=number? m1 1) m2) ((=number? m2 1) m1) ((and (number? m1) (number? m2)) (* m1 m2)) (else (list '* m1 m2)))) (define (=number? exp num) (and (number? exp) (= exp num)))
2.56 (n乗の微分)
(define (exponentiation? x) (and (pair? x) (eq? (car x) '**))) (define (base x) (list-ref x 1)) (define (exponent x) (list-ref x 2)) (define (make-exponentation base exponent) (cond ((=number? exponent 0) 1) ((=number? exponent 1) base) ((=number? base 1) 1) (else (list '** base exponent)))) (define (deriv exp var) (cond ((number? exp) 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 (deriv (multiplier exp) var) (multiplicand exp)))) ((exponentiation? exp) (make-product (make-product (exponent exp) (make-exponentation (base exp) (make-sum (exponent exp) -1))) (deriv (base exp) var))) (else (error "deriv: Unknown expression type" exp))))
2.57 (複数の項を持つ演算子)
(define (augend s) (if (null? (cddr s)) 0 (cons '+ (cddr s)))) (define (multiplicand m) (if (null? (cddr m)) 1 (cons '* (cddr m))))
ここを変更するだけで効くってのはいいね。
2.58 (中置記法)
全部括弧付けされている場合。
(define (sum? x) (and (pair? x) (eq? (list-ref x 1) '+))) (define (addend s) (list-ref s 0)) (define (augend s) (list-ref s 2)) (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 (product? x) (and (pair? x) (eq? (list-ref x 1) '*))) (define (multiplier p) (list-ref p 0)) (define (multiplicand p) (list-ref p 2)) (define (make-product m1 m2) (cond ((or (=number? m1 0) (=number? m2 0)) 0) ((=number? m1 1) m2) ((=number? m2 1) m1) ((and (number? m1) (number? m2)) (* m1 m2)) (else (list m1 '* m2))))
括弧付けされてない場合。
(define (parenthesize e) (cond ((or (not (pair? e)) (<= (length e) 3)) e) ((eq? (list-ref e 1) '*) (parenthesize (append (list (list (car e) (cadr e) (caddr e))) (cdddr e)))) (else (append (list (car e) (cadr e)) (list (parenthesize (cddr e))))) )) (define (deriv/no-paren exp var) (deriv (parenthesize exp) var))
これで上手く行くように思える。