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

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

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

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


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

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


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




실행> python testSyntheticDivision.py 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
,