프로그래밍/Julia

조립제법(Horner의 방법) 예제 2 for Julia

Scripter 2013. 3. 7. 14:14

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

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


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



실행> julia testSyntheticDivision2.jl 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