Продлить суммы и функции продуктов


Упражнения 2.57. Продлить программа дифференциации для обработки сумм и изделий из произвольного числа (два или более) точки зрения. Тогда последний пример выше может быть выражена как

(deriv '(* Х У (+ Х 3)) х)

Попробуйте сделать это, изменив только представление для суммы и произведения, не меняя процедуру deriv на всех. Например, слагаемое из сумма будет первый срок, и augend будет равен сумме остальных условия.

Я написал следующее решение.

(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 (exponent exp)
                       (make-exponentiation (base exp) (- (exponent exp) 1))))
        (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 (make-sum . a)
  (define (iter sum rest) 
    (cond ((null? rest) (if (zero? sum) '() (list sum)))
          ((=number? (car rest) 0) (iter sum (cdr rest)))
          ((number? (car rest)) (iter (+ sum (car rest)) (cdr rest)))
          (else (cons (car rest) (iter sum (cdr rest))))))
  (let ((result (iter 0 a)))
    (if (= (length result) 1)
        (car result)
        (cons '+ result))))

(define (=number? exp num)
  (and (number? exp) (= exp num)))

(define (make-product . a)
  (define (iter product rest)
    (cond ((null? rest) (if (= 1 product) '() (list product)))
          ((=number? (car rest) 1) (iter product 
                                         (cdr rest)))
          ((number? (car rest)) (iter (* product (car rest)) 
                                      (cdr rest)))
          (else 
           (let ((result (iter product (cdr rest))))
             (if (and (pair? result) (eq? (car result) 0))
                 (list 0)
                 (cons (car rest) result))))))
  (let ((result (iter 1 a)))
    (if (= (length result) 1)
        (car result)
        (cons '* result))))

(define (sum? x)
  (and (pair? x) (eq? (car x) '+)))

(define (addend s) (cadr s))

(define (augend s) (if (> (length s) 3)
                       (cons '+ (cddr s))
                       (caddr s)))

(define (product? x)
  (and (pair? x) (eq? (car x) '*)))

(define (multiplier p) (cadr p))

(define (multiplicand p) (if (> (length p) 3) 
                             (cons '* (cddr p))
                             (caddr p)))

(define (exponentiation? x)
  (and (pair? x) (eq? (car x) '**)))
(define (base s) (cadr s))
(define (exponent s) (caddr s))
(define (make-exponentiation m1 m2)
  (cond ((=number? m2 0) 1)
        ((= m2 1) m1)
        (else (list '** m1 m2))))

Его можно улучшить? В частности, посмотрите внимательно на товар и сумма.



380
4
задан 20 апреля 2011 в 06:04 Источник Поделиться
Комментарии
1 ответ

Вы имеете право идеи для реализации делают суммой и сделать продукт. Вы можете улучшить их следующим образом, на мой взгляд.

В течение этих двух функций, вы используете внутреннюю функцию ИТЭР в разделе числовыми и нечисловыми понятиями. Традиционно используется название ИТЭР представляет собой итерационную функцию; ваше определение, тем не менее, это, безусловно, рекурсивные. Чтобы сделать его по-настоящему итерационный, можно использовать два аккумулятора-один для суммы всех числовых терминов и другой-для остальных условий. Затем можно вернуть минусы обоих аккумуляторов, когда итерация заканчивается.

Один может позволить сделать-сумма (и аналогично сделать-товар) для обработки прочих сумме-тип объектов в плане списка, а также-просто тест с суммой?, затем добавить его условия.

Наконец, есть несколько случаев, которые должны быть обработаны, когда итерация заканчивается: остальные может быть пустым или может содержать один или более элементов; сумма-число может быть нулевым или ненулевым.

Вот реализация (нейминг схема немного отличается от вашего ... в ИТЭР функции, условия список остальные термины будут повторяться по, сумма-число - сумма всех числовых выражениях видели до сих пор, остальной список всех нечисловых терминах видели до сих пор):

(define (make-sum . terms)
(define (iter terms sum-numbers rest)
(cond
((null? terms) (cons sum-numbers rest))
((=number? (car terms) 0) (iter (cdr terms) sum-numbers rest))
((number? (car terms)) (iter (cdr terms) (+ sum-numbers (car terms)) rest))
((sum? (car terms)) (iter (append (cdar terms) (cdr terms)) sum-numbers rest))
(else (iter (cdr terms) sum-numbers (cons (car terms) rest)))))
(let*
((result (iter terms 0 null))
(sum-numbers (car result))
(rest (cdr result)))
(if (null? rest)
sum-numbers
(if (zero? sum-numbers)
(if (null? (cdr rest))
(car rest)
(cons '+ rest))
(cons '+ (cons sum-numbers rest))))))

(define (make-product . terms)
(define (iter terms sum-numbers rest)
(cond
((null? terms) (cons sum-numbers rest))
((=number? (car terms) 0) (cons 0 null))
((=number? (car terms) 1) (iter (cdr terms) sum-numbers rest))
((number? (car terms)) (iter (cdr terms) (* sum-numbers (car terms)) rest))
((product? (car terms)) (iter (append (cdar terms) (cdr terms)) sum-numbers rest))
(else (iter (cdr terms) sum-numbers (cons (car terms) rest)))))
(let*
((result (iter terms 1 null))
(sum-numbers (car result))
(rest (cdr result)))
(if (null? rest)
sum-numbers
(if (zero? sum-numbers)
(if (null? (cdr rest))
(car rest)
(cons '* rest))
(cons '* (cons sum-numbers rest))))))

Можно также упростить определение augend и множимое с помощью макияжа сумму и сделать продукт , соответственно:

(define (augend s) (apply make-sum (cddr s)))

(define (multiplicand p) (apply make-product (cddr p)))

Обратите внимание на сходство между сделать-сумму и сделать продукт. Можно выделить какой-то код. Можно также использовать библиотечные функции, такие как раздел (если имеется), чтобы упростить код.

4
ответ дан 24 апреля 2011 в 11:04 Источник Поделиться