미분하는 프로그램 2 - 출력을 개선하기

semmal의 이미지

저번에 만들었던 미분하는 프로그램은 더하기와 곱하기만 지원하고 출력이 그리 보기 좋지 않았습니다.

아래는 음수, 빼기, 거듭제곱의 경우까지 처리하고, 출력까지 더 좋게 만든 형태입니다.

분리하고 합치는 간단한 규칙 몇 개만 추가하면, 이런 공식은 얼마든지 붙여쓸 수 있습니다.

다음에는 prefix가 아니라 infix로 입력을 받고 출력을 하도록 바꿔보도록 하겠습니다.

; symbolic data가 들어오면 미분합니다. 지금은 더하기와 곱하기 밖에 지원하지 않습니다.
; 참고로 미분 공식은 d(u + v)/dx = d(u)/dx + d(v)/dx, d(u * v)/dx = u*(dv/dx) + v*(du/dx) 입니다.
; d(-u)/dx = - d(u)/dx
; d(u - v)/dx = d(u)/dx - d(v)/dx
; d(u^n)/dx = n*n^(n-1)(du/dx) 를 처리할 수 있도록 코드가 추가됩니다.
(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
         (if (same-variable? exp var) 1 0))
        ((negative? exp) (make-negative (deriv (negand exp) var)))
        ((sum? exp)
         (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var)))
        ((difference? exp)
         (make-difference (deriv (minuend exp) var)
                          (deriv (subtrahend 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-exponentiation (base exp)
                                             (make-difference (exponent exp) 1)))
          (deriv (base exp) var)))
        (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 (=number? exp num)
  (and (number? exp) (= exp num)))
 
;(define (make-sum a1 a2) (list '+ a1 a2)) 더 계산을 해서 결과가 보기 좋도록 수정됩니다.
(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 (make-product m1 m2) (list '* m1 m2)) 더 계산을 해서 결과가 보기 좋도록 수정됩니다.
(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 (sum? x)
  (and (pair? x) (eq? (car x) '+)))
 
(define (addend s) (cadr s))
 
(define (augend s) (caddr s))
 
(define (product? x)
  (and (pair? x) (eq? (car x) '*)))
 
(define (multiplier p) (cadr p))
 
(define (multiplicand p) (caddr p))
 
; 여기서부터 음수의 미분에 필요한 코드
(define (make-negative n)
  (cond ((number? n) (- n))
        (else (list '- n))))
 
(define (negative? x)
  (and (pair? x) (eq? (car x) '-) (= (length x) 2)))
 
(define (negand n) (cadr n))
 
; 여기서부터 빼기의 미분에 필요한 코드
(define (make-difference a1 a2)
  (cond ((=number? a1 0) (make-negative a2))
        ((=number? a2 0) a1)
        ((and (number? a1) (number? a2)) (- a1 a2))
        (else (list '- a1 a2))))
 
(define (difference? x)
  (and (pair? x) (eq? (car x) '-) (= (length x) 3)))
 
(define (minuend d) (cadr d))
 
(define (subtrahend d) (caddr d))
 
; 여기서부터 거듭제곱의 미분에 필요한 코드
(define (make-exponentiation e1 e2)
  (cond ((or (=number? e1 0) (=number? e1 1)) e1)
        ((=number? e2 0) 1)
        ((=number? e2 1) e1)
        ((and (number? e1) (number? e2)) (** e1 e2))
        (else (list '** e1 e2))))
 
(define (exponentiation? x)
  (and (pair? x) (eq? (car x) '**)))
 
(define (base e) (cadr e))
 
(define (exponent e) (caddr e))
 
;; 예전 문제와 답
;
;(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)))
 
; 여기서 부터 새로 바뀐 출력
(deriv '(+ x 3) 'x)
;1
 
(deriv '(* x y) 'x)
;y
 
(deriv '(* (* x y) (+ x 3)) 'x)
;(+ (* x y) (* y (+ x 3)))
 
; 음수, 빼기, 거듭제곱 문제
(deriv '(- x) 'x)
;-1
 
(deriv '(- (* x 3) 4) 'x)
;3
 
(deriv '(- (** x 2)) 'x)
;(- (* 2 x))

댓글

권순선의 이미지

태그를 입력하실 때는 반드시 콤마로 구분해 주셔야 합니다... 제가 구분해 드렸는데 다음부터는 콤마를 빼먹지 말아 주세요. :-)

semmal의 이미지

죄송합니다.

익숙치 않아서 실수를 했네요.

다음부터는 신경쓰도록 하겠습니다.

------------------------------
How many legs does a dog have?

------------------------------
How many legs does a dog have?

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.