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

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

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

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



  1. /*
  2.  *  Filename: testSyntheticDivision.groovy
  3.  *
  4.  *  Purpose:  Find the quotient and remainder when some polynomial is
  5.  *            divided by a monic polynomial of the first degree.
  6.  *     이 소스는 자바 소스 TestSyntheticMethod.java 와 내용이 거의 같은
  7.  *    그루비 소스 TestSyntheticMethod.groovy 를 더욱 그루비 소스 코드 답게 수정한 것이다.
  8.  *
  9.  *  Execute: groovy testSyntheticDivision.groovy -2 1 3 3 1
  10.  *
  11.  */
  12. // 사용법 표시
  13. def printUsage() {
  14.      println("사용법: groovy testSyntheticDivision.groovy [수] [피제식의 계수들]")
  15.      println("조립제법(synthetic method)에 의한 다항식 나눗셈 결과를 보여준다.")
  16. }
  17. // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  18. String simplify(double v) {
  19.     String t = "" + v
  20.     if (t.endsWith(".0"))
  21.         t = t[0..<(t.length() - 2)]
  22.     return t
  23. }
  24. // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  25. // 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  26. String simplify(double v, int width) {
  27.     String t = "" + v
  28.     if (t.endsWith(".0"))
  29.         t = t[0..<(t.length() - 2)]
  30.     int len = t.length()
  31.     if (len < width)
  32.         t = "               ".substring(0, width - len) + t
  33.     return t;
  34. }
  35. // 다항식을 내림차순의 스트링 표현으로 반환
  36. String toPolyString(double[] c) {
  37.     String t = ""
  38.     def sc0 = simplify(c[0])
  39.     if (c.length > 2) {
  40.         if (sc0 == "1")
  41.             t += "x^" + (c.length-1)
  42.         else if (sc0 == "-1")
  43.             t += "-x^" + (c.length-1)
  44.         else
  45.             t += sc0 + " x^" + (c.length-1)
  46.     }
  47.     else if (c.length == 2) {
  48.         if (sc0 == "1")
  49.             t += "x"
  50.         else if (sc0 == "-1")
  51.             t += "-x"
  52.         else
  53.             t += sc0 + " x"
  54.     }
  55.     else if (c.length == 1) {
  56.         t += sc0
  57.     }
  58.     for (i in 1..< c.length) {
  59.         def k = c.length - 1 - i
  60.         def sc = simplify(c[i])
  61.         if (k > 1) {
  62.             if (c[i] > 0.0) {
  63.                 if (sc == "1")
  64.                     t += " + " + "x^" + k
  65.                 else
  66.                     t += " + " + sc + " x^" + k
  67.             }
  68.             else if (c[i] < 0.0) {
  69.                 if (sc == "-1")
  70.                     t += " - " + "x^" + k
  71.                 else
  72.                     t += " - " + simplify(Math.abs(c[i])) + " x^" + k
  73.             }
  74.         }
  75.         else if (k == 1) {
  76.             if (c[i] > 0.0) {
  77.                 if (sc == "1")
  78.                     t += " + " + "x"
  79.                 else
  80.                     t += " + " + sc + " x"
  81.             }
  82.             else if (c[i] < 0.0) {
  83.                 if (sc == "-1")
  84.                     t += " - " + "x"
  85.                 else
  86.                     t += " - " + simplify(Math.abs(c[i])) + " x"
  87.             }
  88.         }
  89.         else if (k == 0) {
  90.             if (c[i] > 0.0) {
  91.                 t += " + " + sc
  92.             }
  93.             else if (c[i] < 0.0)
  94.                 t += " - " + simplify(Math.abs(c[i]))
  95.         }
  96.     }
  97.     return t
  98. }
  99. // 다항식 나눗셈 결과를
  100. //     (피제식) = (제식)(몫) + (나마지)
  101. // 형태로 출력
  102. def printDivisionResult(double a, double[] c, double[] b) {
  103.     print("  " + toPolyString(c))
  104.     println()
  105.     print("    = ( " + toPolyString( [1.0, -a] as double[] ) + " )")
  106.     double[] tmp = new double[b.length - 1]
  107.     for (i in 0..<tmp.length) {
  108.         tmp[i] = b[i]
  109.     }
  110.     print("( " + toPolyString(tmp) + " )")
  111.     double r = b[b.length - 1]
  112.     if (r > 0.0)
  113.         print(" + " + simplify(r))
  114.     else if (r < 0.0)
  115.         print(" - " + simplify(Math.abs(r)))
  116.     println()
  117. }
  118. // 조립제법 계산표 출력 함수
  119. def printSyntheticTable(double a, double[] c, double[] s, double[] q) {
  120.     print("       | ")
  121.     print(simplify(c[0], 6))
  122.     for (i in 1..< c.length) {
  123.         print("  " + simplify(c[i], 6))
  124.     }
  125.     println()
  126.     print(simplify(a, 6) + " | ")
  127.     print("        ")
  128.     print(simplify(s[1], 6))
  129.     for (i in 2..< s.length) {
  130.         print("  " + simplify(s[i], 6))
  131.     }
  132.     println()
  133.     print("       |-")
  134.     for (i in 0..< q.length) {
  135.         print("--------")
  136.     }
  137.     println()
  138.     print("         ")
  139.     print(simplify(q[0], 6))
  140.     for (i in 1..< q.length) {
  141.         print("  " + simplify(q[i], 6))
  142.     }
  143.     println()
  144. }
  145. // 실행 시작 지점
  146. if (args.length < 3) {
  147.     printUsage()
  148.     System.exit(1);
  149. }
  150. double a = Double.parseDouble(args[0])
  151. double[] c = new double[args.length - 1]
  152. double[] s = new double[c.length]
  153. double[] b = new double[c.length]
  154. for (i in 0..<c.length) {
  155.     c[i] = Double.parseDouble(args[i + 1])
  156. }
  157. s[0] = 0.0;
  158. b[0] = c[0];
  159. for (i in 1..<c.length) {
  160.     s[i] = b[i-1]*a
  161.  b[i] = c[i] + s[i]
  162. }
  163. print("몫의 계수는 ");
  164. for (i in 0..<(b.length - 2)) {
  165.     print(simplify(b[i]) + ", " )
  166. }
  167. print(simplify(b[b.length - 2]))
  168. println(" 이고, 나머지는 " + simplify(b[b.length - 1]) + " 이다.")
  169. println()
  170. printSyntheticTable(a, c, s, b)
  171. println()
  172. printDivisionResult(a, c, b)



groovy 명령으로 아래와 같이 실행하여 보았다.


실행> groovy testSyntheticDivision.groovy 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



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