Trình bày các biểu thức đại số

Chúng ta có nhiều cách để sử dụng cấu trúc list trình bày các biểu thức đại số. Ví dụ, chúng ta có thể sử dụng list các biểu tượng để trình bày các khái niệm đại số, như ax+b như là một list ( a*x + b). Tuy nhiên, một cách tốt nhất là sử dụng cặp dấu ngoặc đơn, mà Lisp sử dụng để combination; để trình bày ax+b chúng ta có thể sử dụng (+ (* a x) b). Vậy nên để trình bày vi phân chúng ta có thể follow theo như sau:

  • Các biến là symbol, được xác định bởi dự đón symbols?
    (define (variable? x) (symbol? x))
  • Hai biến tương tự nếu giá trị symbol của chúng bằng nhau.
    (define (same-variable? v1 v2)
    (and (variable? v1) (variable? v2) (eq? v1 v2)))
  • Sum và produce được khởi tạo như môt list
    (define (make-sum a1 a2) (list ‘+ a1 a2))
    (define (make-product m1 m2) (list ‘* m1 m2))
  • Một sum của list thì thành phần đầu tiên là symbol +
    (define (sum? x) (and (pair? x) (eq? (car x) ‘+)))
  • Addend là item thứ hai của list sum
    (define (addend s) (cadr s))
  • Augend là item thứ ba của list sum
    (define (augend s) (caddr s))
  • Product tương tự như với sum, nơi item đàu là symbol * (define (product? x) (and (pair? x) (eq? (car x) ‘*)))
  • (define (multiplier p) (cadr p))
  • :(define (multiplicand p) (caddr p))

Hơn nữa, chúng ta cần bao gồm điều này với thuật toán để tận dụng procedure deriv để có một chương trình vi phân đại số. Cùng xem qua vài ví dụ

(deriv '(+ x 3) 'x)
(+ 1 0)
(deriv '(* x y) 'x)
(+ (* x 0) (* 1 y))
(deriv '(* (* x y) (+ x 3)) 'x)
(+ (* (* x y) (+ 1 0))
(* (+ (* x 0) (* 1 y))
(+ x 3)))

Chương trình đưa ra các câu trả lời đúng, tuy nhiên, chúng không cụ thể. Sự thật rằng.

nhưng chúng ta muốn chương trình biết rằng x.0 = 0 và 1.y =y và 0 + y = y. Trả lời cho ví dụ thứ hai đơn giản là y. Ví dụ thứ 3 trở thành một vấn đề nghiêm trọng khi biểu thức phức tạp.

Một điều khó khăn chúng ta gặp phải là vẫn chưa giảm câu trả lời đến đơn giản nhất. Để đạt được sự giảm kết quả đơn giản trong phân số, chúng ta chỉ cần thay đổi constructor và selector. Chúng ta có thể thực thi chiến lược tương tự. Chúng ta không thay đổi thực thi của deriv. Thay vào đó chúng ta sẽ thay đổi make-sum vì thế kể cả các summand là số, make-sum sẽ thêm chúng và trả về tổng. Và nếu một summand là 0, thì make-sum sẽ trả về summand còn lại.

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

Sử dụng procedure =number?, nó kiểm tra liệu một biểu thức có bằng một số cho trước

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

Tương tự, chúng ta sẽ thay đổi make-proceduct để tạo quy tắc rằng 0 nhân với bất kỳ thứ gì cũng là 0 và 1 nhân với bất kỳ thứ gì cũng là chính nó.

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

Đây là cách mà procedure hoat động,

(deriv '(+ x 3) 'x)
1
(deriv '(* x y) 'x)
y
(deriv '(* (* x y) (+ x 3)) 'x)
(+ (* x y) (* y (+ x 3)))

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *