다항식 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.py 를 수정한 것이다.

python 대신 jython이나 IronPython 으로도 수정 없이 그대로 실행된다.


  1. # coding: MS949
  2. #  Filename: testSyntheticDivision2.py
  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:  python testSyntheticDivision2.py 5 -4 7 8 6 8
  8. #        Or  jython testSyntheticDivision2.py 5 -4 7 8 6 8
  9. import sys
  10. # 사용법 표시
  11. def printUsage():
  12.     print("사용법: python testSyntheticDivision2.py [제식의 계수] [피제식의 계수들]")
  13.     print("조립제법(synthetic method)에 의한 다항식 나눗셈 결과를 보여준다.")
  14. # 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  15. # 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  16. def simplify(v, width=None):
  17.     t = "%g" % v
  18.     tlen = len(t)
  19.     if t[tlen-2:tlen-1] == ".0":
  20.         t = t[0, -2]
  21.     if width != None:
  22.         if tlen < width:
  23.             t = "              "[0: width - tlen] + t
  24.     return t
  25. # "/수" 표시하기
  26. # 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  27. # 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  28. def simplifyReciprocal(v, width=None):
  29.     t = "/%g" % v
  30.     tlen = len(t)
  31.     if t[tlen-2:tlen-1] == ".0":
  32.         t = t[0, -2]
  33.     if width != None:
  34.         if tlen < width:
  35.             t = "              "[0: width - tlen] + t
  36.     return t
  37. # 다항식을 내림차순의 스트링 표현으로 반환
  38. def toPolyString(c):
  39.     t = ""
  40.     sc0 = simplify(c[0])
  41.     if len(c) > 2:
  42.         if sc0 == "1":
  43.             t += "x^%d" % (len(c)-1)
  44.         elif sc0 == "-1":
  45.             t += "-x^%d" % (len(c)-1)
  46.         else:
  47.             t += sc0 + " x^%d" % (len(c)-1)
  48.     elif len(c) == 2:
  49.         if sc0 == "1":
  50.             t += "x"
  51.         elif sc0 == "-1":
  52.             t += "-x"
  53.         else:
  54.             t += sc0 + " x"
  55.     elif len(c) == 1:
  56.         t += sc0
  57.     for i in range(1, len(c)):
  58.         k = len(c) - 1 - i
  59.         sc = simplify(c[i])
  60.         if k > 1:
  61.             if c[i] > 0.0:
  62.                 if sc == "1":
  63.                     t += " + " + "x^%d" % k
  64.                 else:
  65.                     t += " + " + sc + " x^%d" % k
  66.             elif c[i] < 0.0:
  67.                 if sc == "-1":
  68.                     t += " - " + "x^%d" % k
  69.                 else:
  70.                     t += " - " + simplify(abs(c[i])) + " x^%d" % k
  71.         elif k == 1:
  72.             if c[i] > 0.0:
  73.                 if sc == "1":
  74.                     t += " + " + "x"
  75.                 else:
  76.                     t += " + " + sc + " x"
  77.             elif c[i] < 0.0:
  78.                 if sc == "-1":
  79.                     t += " - " + "x"
  80.                 else:
  81.                     t += " - " + simplify(abs(c[i])) + " x"
  82.         elif k == 0:
  83.             if c[i] > 0.0:
  84.                 t += " + " + sc
  85.             elif c[i] < 0.0:
  86.                 t += " - " + simplify(abs(c[i]))
  87.     return t
  88. # 다항식 나눗셈 결과를
  89. #     (피제식) = (제식)(몫) + (나머지)
  90. # 형태로 출력
  91. def printDivisionResult(a, c, d, b):
  92.     strLine = "  " + toPolyString(c)
  93.     print( strLine )
  94.     strLine = "    = ( " + toPolyString( [a[0], -a[1]] ) + " )"
  95.     tmp = [0.0] * (len(b) - 1)
  96.     for i in range(0, len(tmp)):
  97.         tmp[i] = b[i]
  98.     strLine += "( " + toPolyString(tmp) + " )"
  99.     r = d[len(d) - 1]
  100.     if r > 0.0:
  101.         strLine += " + " + simplify(r)
  102.     elif r < 0.0:
  103.         strLine += " - " + simplify(abs(r))
  104.     print( strLine )
  105. # 조립제법 계산표 출력 함수
  106. def printSyntheticTable(a, c, s, d, q):
  107.     strLine = "         | "
  108.     strLine += simplify(c[0], 8)
  109.     for i in range(1, len(c)):
  110.         strLine += "  " + simplify(c[i], 8)
  111.     print( strLine )
  112.     strLine = simplify(a[1], 8) + " |"
  113.     strLine += "           "
  114.     strLine += simplify(s[1], 8)
  115.     for i in range(2, len(s)):
  116.         strLine += "  " + simplify(s[i], 8)
  117.     print( strLine )
  118.     strLine = "         |"
  119.     for i in range(0, len(q)):
  120.         strLine += "----------"
  121.     print( strLine )
  122.     strLine = "         | "
  123.     strLine += simplify(d[0], 8)
  124.     for i in range(1, len(d)):
  125.         strLine += "  " + simplify(d[i], 8)
  126.     print( strLine )
  127.     strLine = simplifyReciprocal(a[0], 8) + " | "
  128.     strLine += simplify(q[0], 8)
  129.     for i in range(1, len(q) - 1):
  130.         strLine += "  " + simplify(q[i], 8)
  131.     print( strLine )
  132. # 실행 시작 지점
  133. if len(sys.argv) < 3:
  134.     printUsage()
  135.     sys.exit(1)
  136. ######################################################
  137. # 피제식은 c_0 x^n +  c_1 x^(n -1) + ... + c_n
  138. # 제식은 a x -  b
  139. a = [float(sys.argv[1]), - float(sys.argv[2])]
  140. c = [0.0]*(len(sys.argv) - 3)
  141. s = [0.0]*(len(sys.argv) - 3)
  142. d = [0.0]*(len(sys.argv) - 3)
  143. b = [0.0]*(len(sys.argv) - 3)
  144. for i in range(0, len(c)):
  145.     c[i] = float(sys.argv[i + 3])
  146. ######################################################
  147. # 조립제법의 주요 부분
  148. s[0] = 0.0
  149. d[0] = c[0]
  150. b[0] = c[0] / a[0]
  151. for i in range(1, len(c)):
  152.     s[i] = b[i-1]*a[1]
  153.     d[i] = c[i] + s[i]
  154.     b[i] = d[i] / a[0]
  155. ######################################################
  156. # 몫의 계수와 나머지를 출력한다.
  157. print("몫의 계수는"),
  158. for i in range(0, len(b) - 2):
  159.     print(simplify(b[i], None) + ", " ),
  160. print(simplify(b[len(b) - 2], None)),
  161. print("이고, 나머지는 " + simplify(d[len(d) - 1], None) + " 이다.")
  162. print
  163. ######################################################
  164. # 조립제법 표를 출력한다.
  165. printSyntheticTable(a, c, s, d, b)
  166. print
  167. ######################################################
  168. # (피제식) = (제식) x (몫) + (나머지)
  169. printDivisionResult(a, c, d, b)




실행> python testSyntheticDivision2.py 5 -4 7 8 6 8
몫의 계수는 1.4,  2.72,  3.376 이고, 나머지는 21.504 이다.

         |        7         8         6         8
       4 |                5.6     10.88    13.504
         |----------------------------------------
         |        7      13.6     16.88    21.504
      /5 |      1.4      2.72     3.376

  7 x^3 + 8 x^2 + 6 x + 8
    = ( 5 x - 4 )( 1.4 x^2 + 2.72 x + 3.376 ) + 21.504



Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

Posted by Scripter
,