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

         p(x) = (ax - b)q(x) + r

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

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


아래의 소스파일은 이전에 작성했던 파일 testSyntheticDivision.lsp 를 수정한 것이다.

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




실행> clisp testSyntheticDivision2.lsp 5 -4 7 8 6 8

몫의 계수는 1.4, 2.72, 3.3760002 이고, 나머지는 21.504002 이다. | 7 8 6 8 4 | 5.6 10.88 13.504001 |------------------------------------------------ | 7 13.6 16.880001 21.504002 /5 | 1.4 2.72 3.3760002 7 x^3 + 8 x^2 + 6 x + 8 = ( 5 x - 4 )( 1.4 x^2 + 2.72 x + 3.3760002 ) + 21.504002

 

 

Posted by Scripter
,