다항식 p(x) 를 1차 다항식 x - a 로 나눌 때의 몫과 나머지를 구하는 조립제법을
Common Lisp 언어로 구현해 보았다. 조립제법은 일명 Horner의 방법이라고도 불리우는데, 이는 x = a 에서 다항식 p(x)의 값 p(a)을 계산하는 가장 빠른 알고리즘이기도 하다.

         p(x) = (x - a)q(x) + r

여기서 r은 나머지이며 r = p(a) 이다. 또 q(x)는 몫이다.

[참고]
    * 온라인으로 조립제법 표 만들기 손으로 계산하는 조립제법 표 
    * 온라인으로 구하는 다항식의 도함수: 조립제법을 이용한 다항식의 도함수


아래의 소스파일은 Python용 소스파일 testSyntheticDivision.py를 Common Lisp용으로 수정한 것이다. 

실행은 CLisp을 사용한다.


  1. #!/usr/bin/env clisp
  2. ;;  Filename: testSyntheticDivision.lsp
  3. ;;
  4. ;;  Purpose:  Find the quotient and remainder when some polynomial is
  5. ;;            divided by a monic polynomial of the first degree.
  6. ;;
  7. ;;  Execute:  clisp testSyntheticDivision.lsp -2 1 3 3 1
  8. ;;
  9. ;;  Date: 201. 8. 31.
  10. ;; 사용법 표시
  11. (defun printUsage()
  12.     (format t "사용법: python testSyntheticDivision.py [수] [피제식의 계수들]~%")
  13.     (format t "조립제법(synthetic method)에 의한 다항식 나눗셈 결과를 보여준다.~%"))
  14. ;; 스트링을 부동소수점수로 변환하는 함수
  15. (defun parse-number (v)
  16.      (with-input-from-string (s v) (read s)))
  17. ;; 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  18. ;; 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  19. (defun simplify(v width)
  20.     (setf tt (format nil "~F" v))
  21.     (setf tlen (length tt))
  22.     (if (> tlen 1) (progn
  23.         (if (equal (substring tt (- tlen 2) tlen) ".0") (progn
  24.             (setf tt (substring tt 0 (- tlen 2)))
  25.             (setf tlen (length tt))
  26.             )
  27.           )
  28.     ))
  29.     (if (not (equal width nil)) (progn
  30.         (if (< tlen width) (progn
  31.             (setf tt (concatenate 'string (substring "              " 0 (- width tlen)) tt)) ))
  32.         )
  33.     )
  34.     tt )
  35. ;; 다항식을 내림차순의 스트링 표현으로 반환
  36. (defun toPolyString(c)
  37.     (setf ttt "")
  38.     (setf sc0 (simplify (nth 0 c) nil ))
  39.     (setf sc0 (simplify (nth 0 c) nil ))
  40.     (if (> (length c) 2)
  41.         (cond
  42.            ((equal sc0 "1") (setf ttt (concatenate 'string ttt (format nil "x^~D" (- (length c) 1)))))
  43.            ((equal sc0 "-1") (setf ttt (concatenate 'string ttt (format nil "-x^~D" (- (length c) 1)))))
  44.            (t (setf ttt (concatenate 'string ttt sc0 (format nil " x^~D" (- (length c) 1)))))
  45.         )
  46.     )
  47.     (if (= (length c) 2)
  48.         (cond
  49.            ((equal sc0 "1") (setf ttt (concatenate 'string ttt "x")))
  50.            ((equal sc0 "-1") (setf ttt (concatenate 'string ttt "-x")))
  51.            (t (setf ttt (concatenate 'string ttt sc0 " x")))
  52.         )
  53.     )
  54.     (if (= (length c) 1)
  55.            (setf ttt (concatenate 'string ttt sc0))
  56.     )
  57.     (loop for i from 1 below (length c) do
  58.         (setf k (- (length c) 1 i))
  59.         (setf sc (simplify (nth i c) nil))
  60.         (if (> k 1) (progn
  61.             (cond
  62.                 ((> (nth i c) 0.0)
  63.                     (if (equal sc "1")
  64.                         (setf ttt (concatenate 'string ttt " + " (format nil "x^~D" k)))
  65.                         (setf ttt (concatenate 'string ttt " + " sc (format nil " x^~D" k)))
  66.                     ) )
  67.                 ((< (nth i c) 0.0)
  68.                     (if (equal sc "-1")
  69.                         (setf ttt (concatenate 'string ttt " - " (format nil "x^~D" k)))
  70.                         (setf ttt (concatenate 'string ttt " - " (simplify (abs (nth i c)) nil) (format nil " x^~D" k)))
  71.                     ) )
  72.                 )
  73.             )
  74.         )
  75.         (if (= k 1)
  76.             (cond
  77.                 ((> (nth i c) 0.0)
  78.                     (if (equal sc "1")
  79.                         (setf ttt (concatenate 'string ttt " + " "x"))
  80.                         (setf ttt (concatenate 'string ttt " + " sc " x"))
  81.                     ) )
  82.                 ((< (nth i c) 0.0)
  83.                     (if (equal sc "-1")
  84.                         (setf ttt (concatenate 'string ttt " - " "x"))
  85.                         (setf ttt (concatenate 'string ttt " - " (simplify (abs (nth i c)) nil) " x"))
  86.                     ) )
  87.             )
  88.         )
  89.         (if (= k 0)
  90.             (cond
  91.                 ( (> (nth i c) 0.0) (setf ttt (concatenate 'string ttt " + " sc)) )
  92.                 ( (< (nth i c) 0.0) (setf ttt (concatenate 'string ttt " - " (simplify (abs (nth i c)) nil) )) )
  93.             )
  94.         )
  95.     )
  96. ;; 다항식 나눗셈 결과를
  97. ;;     (피제식) = (제식)(몫) + (나머지)
  98. ;; 형태로 출력
  99. (defun printDivisionResult(a c b)
  100.     (setf strLine (concatenate 'string "  " (toPolyString c)))
  101.     (format t "~A~%" strLine)
  102.     (setf strLine (concatenate 'string "    = ( " (toPolyString (list 1.0 (- a))) " )"))
  103.     (setf tmp (make-list (- (length b) 1) :initial-element 0.0)) 
  104.     (loop for i from 0 below (length tmp) do
  105.         (setf (nth i tmp) (nth i b)) )
  106.     (setf strLine (concatenate 'string strLine "( " (toPolyString tmp) " )"))
  107.     (setf r (nth (- (length b) 1) b))
  108.     (cond
  109.        ((> r 0.0)  (setf strLine (concatenate 'string strLine " + " (simplify r nil) )))
  110.        ((< r 0.0)  (setf strLine (concatenate 'string strLine " - " (simplify (abs r) nil) )))
  111.     )
  112.     (format t "~A~%" strLine)
  113. )
  114. ;; 조립제법 계산표 출력 함수
  115. (defun printSyntheticTable(a c s q)
  116.     (setf strLine "       | ")
  117.     (setf strLine (concatenate 'string strLine (simplify (nth 0 c) 6) ))
  118.     (loop for i from 1 below (length c) do
  119.         (setf strLine (concatenate 'string strLine "  " (simplify (nth i c) 6) )))
  120.     (format t "~A~%" strLine)
  121.     (setf strLine (concatenate 'string (simplify a 6) " |"))
  122.     (setf strLine (concatenate 'string strLine "         "))
  123.     (setf strLine (concatenate 'string strLine (simplify (nth 1 s) 6)))
  124.     (loop for i from 2 below (length s) do
  125.         (setf strLine (concatenate 'string strLine "  " (simplify (nth i s) 6) )))
  126.     (format t "~A~%" strLine)
  127.     (setf strLine "       |")
  128.     (loop for i from 0 below (length q) do
  129.         (setf strLine (concatenate 'string strLine "--------")))
  130.     (format t "~A~%" strLine)
  131.     (setf strLine "         ")
  132.     (setf strLine (concatenate 'string strLine (simplify (nth 0 q) 6)))
  133.     (loop for i from 1 below (length q) do
  134.         (setf strLine (concatenate 'string strLine "  " (simplify (nth i q) 6) )))
  135.     (format t "~A~%" strLine)
  136. )
  137. ;; 실행 시작 지점
  138. (if (< (length ext:*args*) 3) (progn
  139.     (printUsage)
  140.     (quit) ))
  141. ;; ----------------------------------------------------
  142. ;; 피제식은 c_0 x^n +  c_1 x^(n -1) + ... + c_n
  143. ;; 제식은 x -  a
  144. (setf a (parse-number (nth 0 ext:*args*)) )
  145. (setf c (make-list (- (length ext:*args*) 1) :initial-element 0.0) )
  146. (setf s (make-list (- (length ext:*args*) 1) :initial-element 0.0) )
  147. (setf b (make-list (- (length ext:*args*) 1) :initial-element 0.0) )
  148. (loop for i from 0 below (length c) do
  149.     (setf (nth i c) (parse-number (nth (+ i 1) ext:*args*))))
  150. ;; ----------------------------------------------------
  151. ;; 조립제법의 주요 부분
  152. (setf (nth 0 s) 0.0)
  153. (setf (nth 0 b) (nth 0 c))
  154. (loop for i from 1 below (length c) do
  155.     (setf (nth i s) (* (nth (- i 1) b) a))
  156.     (setf (nth i b) (+ (nth i c) (nth i s))) )
  157. ;; ----------------------------------------------------
  158. ;; 몫의 계수와 나머지를 출력한다.
  159. (format t "몫의 계수는 ")
  160. (loop for i from 0 below (- (length b) 2) do
  161.     (format t (concatenate 'string (simplify (nth i b) nil) ",  ")))
  162. (format t (concatenate 'string (simplify (nth (- (length b) 2) b) nil) " "))
  163. (format t (concatenate 'string "이고, 나머지는 " (simplify (nth (- (length b) 1) b) nil) " 이다.~%"))
  164. (terpri)
  165. ;; ----------------------------------------------------
  166. ;; 조립제법 표를 출력한다.
  167. (printSyntheticTable a c s b)
  168. (terpri)
  169. ;; ----------------------------------------------------
  170. ;; (피제식) = (제식) x (몫) + (나머지)
  171. (printDivisionResult a c b)




실행> clisp testSyntheticDivision.lsp 1 2 3 4 5
몫의 계수는 2, 5, 9 이고, 나머지는 14 이다.

       |      2       3       4       5
     1 |              2       5       9
       |---------------------------------
              2       5       9      14

  2 x^3 + 3 x^2 + 4 x + 5
    = ( x - 1 )( 2 x^2 + 5 x + 9 ) + 14



 

Posted by Scripter
,