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

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

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

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



  1. /*
  2.  *  Filename: testSyntheticDivision.scala
  3.  *
  4.  *  Purpose:  Find the quotient and remainder when some polynomial is
  5.  *            divided by a monic polynomial of the first degree.
  6.  *     이 소스는 그루비 소스 testSyntheticDivision.groovy 를
  7.  *     스칼라 소스로 변환한 것이다.
  8.  *
  9.  *  Execute: scala -encoding MS949 testSyntheticDivision.scala -2 1 3 3 1
  10.  *
  11.  */
  12. // 사용법 표시
  13. def printUsage() {
  14.      println("사용법: scala testSyntheticDivision.scala [수] [피제식의 계수들]")
  15.      println("조립제법(synthetic method)에 의한 다항식 나눗셈 결과를 보여준다.")
  16. }
  17. // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  18. def simplify(v: Double) : String = {
  19.     var t : String = "" + v 
  20.     if (t.endsWith(".0"))
  21.         t = t.substring(0, t.length - 2)
  22.     return t
  23. }
  24. // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  25. // 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  26. def simplify(v: Double, width: Int) : String = {
  27.     var t : String = "" + v
  28.     if (t.endsWith(".0"))
  29.         t = t.substring(0, t.length - 2)
  30.     var len : Int = t.length
  31.     if (len < width)
  32.         t = "               ".substring(0, width - len) + t
  33.     return t;
  34. }
  35. // 다항식을 내림차순의 스트링 표현으로 반환
  36. def toPolyString(c : Array[Double]) : String = {
  37.     var t : String = ""
  38.     var sc0 : String = 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 <- List.range(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((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(a : Double, c : Array[Double], b : Array[Double]) {
  103.     print("  " + toPolyString(c))
  104.     println()
  105.     print("    = ( " + toPolyString( Array(1.0, -a)  ) + " )")
  106.     var tmp : Array[Double] = new Array[Double](b.length - 1)
  107.     for (i <- List.range(0, tmp.length)) {
  108.         tmp(i) = b(i)
  109.     }
  110.     print("( " + toPolyString(tmp) + " )")
  111.     var r : Double = 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(a : Double, c : Array[Double], s : Array[Double], q : Array[Double]) {
  120.     print("       | ")
  121.     print(simplify(c(0), 6))
  122.     for (i <- List.range(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 <- List.range(2, s.length)) {
  130.         print("  " + simplify(s(i), 6))
  131.     }
  132.     println()
  133.     print("       |-")
  134.     for (i <- List.range(0, q.length)) {
  135.         print("--------")
  136.     }
  137.     println()
  138.     print("         ")
  139.     print(simplify(q(0), 6))
  140.     for (i <- List.range(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. var a : Double = args(0).toDouble
  151. var c : Array[double] = new Array[Double](args.length - 1)
  152. var s : Array[double] = new Array[Double](c.length)
  153. var b : Array[double] = new Array[Double](c.length)
  154. for (i <- List.range(0, c.length)) {
  155.     c(i) = args(i + 1).toDouble
  156. }
  157. s(0) = 0.0
  158. b(0) = c(0)
  159. for (i <- List.range(1, c.length)) {
  160.     s(i) = b(i-1)*a
  161.     b(i) = c(i) + s(i)
  162. }
  163. print("몫의 계수는 ")
  164. for (i <- List.range(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)



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


실행> scala -encoding MS949 testSyntheticDivision.scala 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
,