프로그래밍/Io

조립제법(Horner의 방법) 예제 for Io

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

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

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

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



  1. #  Filename: testSyntheticDivision.io
  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: io testSyntheticDivision.io -2 1 3 3 1
  7. // 사용법 표시
  8. printUsage := method (
  9.     "Usage: io testSyntheticDivision.io [number] [coefficients of denominator]" println
  10.      "Display the result of a synthetic division on the console." println
  11. )
  12. // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  13. simplify := method(v,
  14.     t := "" .. v
  15.     if ((t size) > 2 and (t silce(t size - 2) == ".0")) then (
  16.         t = t silce(t size - 2)
  17.     )
  18.     t
  19. )
  20. // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  21. // 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  22. simplify := method(v, width,
  23.     t := "" .. v
  24.     if ((t size) > 2 and (t silce(t size - 2) == ".0")) then (
  25.         t = t silce(t size - 2)
  26.     )
  27.     len := t size
  28.     if (len < width) then (
  29.         t = "               " slice(0, width - len) .. t
  30.     )
  31.     t
  32. )
  33. // 다항식을 내림차순의 스트링 표현으로 반환
  34. toPolyString := method(c,
  35.     t := ""
  36.     sc0 := simplify(c at(0), 0 )
  37.     if (c size  > 2) then (
  38.         if (sc0 == "1")  then (
  39.             t = t .. "x^" .. (c size - 1)
  40.         ) elseif (sc0 == "-1")  then (
  41.             t = t .. "-x^" .. (c size - 1)
  42.         ) else (
  43.             t = t .. sc0 .. " x^" .. (c size - 1)
  44.         )
  45.     ) elseif (c size == 2)  then (
  46.         if (sc0 == "1")   then (
  47.             t = t .. "x"
  48.         ) elseif (sc0 == "-1")  then (
  49.             t = t .. "-x"
  50.         ) else (
  51.             t = t .. sc0 .. " x"
  52.         )
  53.     ) elseif (c size == 1)  then (
  54.         t = t .. sc0
  55.     )
  56.     for (i, 1, c size - 1,
  57.         k := c size - 1 - i
  58.         sc := simplify(c at(i), 0)
  59.         if (k > 1) then (
  60.             if (c at(i) asNumber > 0.0) then (
  61.                 if (sc == "1") then ( 
  62.                     t = t .. " + " .. "x^" .. k
  63.                 ) else (
  64.                     t = t .. " + " .. sc .. " x^" .. k
  65.                 )
  66.             ) elseif (c at(i) asNumber < 0.0) then (
  67.                 if (sc == "-1") then (
  68.                     t = t .. " + " .. "x^" .. k
  69.                 ) else (
  70.                     t = t .. " - " .. simplify(c at(i) abs, 0) .. " x^" .. k
  71.                 )
  72.             )
  73.         ) elseif (k == 1) then (
  74.             if (c at(i) asNumber > 0.0)  then (
  75.                 if (sc == "1") then (
  76.                     t = t .. " + " .. "x"
  77.                 ) else (
  78.                     t = t .. " + " .. sc .. " x"
  79.                 )
  80.             ) elseif (c at(i) asNumber < 0.0) then (
  81.                 if (sc == "-1") then (
  82.                     t = t .. " - " .. "x"
  83.                 ) else (
  84.                     t = t .. " - " .. simplify(c at(i) asNumber abs, 0) .. " x"
  85.                 )
  86.             )
  87.         ) elseif (k == 0) then (
  88.             if (c at(i)  asNumber > 0.0) then (
  89.                 t = t .. " + " .. sc
  90.             ) elseif (c at(i)  asNumber < 0.0) then (
  91.                 t = t .. " - " .. simplify(c at(i)  asNumber abs, 0)
  92.             )
  93.         )
  94.     ) 
  95.     t
  96. )
  97. // 다항식 나눗셈 결과를
  98. //     (피제식) = (제식)(몫) + (나마지)
  99. // 형태로 출력
  100. printDivisionResult := method(a, c, b,
  101.     ("  " .. toPolyString(c)) print
  102.     "" println
  103.     ("    = ( " .. toPolyString( list(1.0, -a) ) .. " )") print
  104.     tmp := list()
  105.     for (i, 0, b size - 2,
  106.         tmp append(0.0)
  107.     )
  108.     for (i, 0, tmp size - 1,
  109.         tmp atPut(i, b at(i) asNumber)
  110.     )
  111.     ("( " .. toPolyString(tmp) .. " )") print
  112.     r := b at(b size - 1)
  113.     if (r > 0.0) then (
  114.         (" + " .. simplify(r, 0), 0) print
  115.     ) elseif (r < 0.0) then (
  116.         (" - " .. simplify(r abs, 0), 0) print
  117.     )
  118.     "" println
  119. )
  120. // 조립제법 계산표 출력 함수
  121. printSyntheticTable := method(a, c, s, q,
  122.     "       | " print
  123.     simplify(c at(0), 6) print
  124.     for (i, 1, c size - 1,
  125.         ("  " .. simplify(c at(i), 6)) print
  126.     )
  127.     "" println
  128.     (simplify(a, 6) .. " | ") print
  129.     "        " print
  130.     simplify(s at(1), 6) print
  131.     for (i, 2, s size - 1,
  132.         ("  " .. simplify(s at (i), 6)) print
  133.     )
  134.     "" println
  135.     "       |-" print
  136.     for (i, 0, q size - 1,
  137.         "--------" print
  138.     )
  139.     "" println
  140.     "         " print
  141.     simplify(q at(0), 6) print
  142.     for (i, 1, q size - 1,
  143.         ("  " .. simplify(q at(i), 6)) print
  144.     )
  145.     "" println
  146. )
  147. // 실행 시작 지점
  148. if (args size  < 4) then (
  149.     printUsage()
  150.     exit(1)
  151. )
  152. a := (args at(1)) asNumber
  153. c := list()
  154. s := list()
  155. b := list()
  156. for (i, 0, args size - 3,
  157.     c append(args at(i + 2))
  158. )
  159. for (i, 0, c size - 1,
  160.     s append(0.0)
  161.     b append(0.0)
  162. )
  163. s atPut(0, 0.0)
  164. b atPut(0, c at(0))
  165. for (i, 1, c size - 1,
  166.     s atPut(i,  (b at(i-1) asNumber)*a )
  167.     b atPut(i,  (c at(i) asNumber) + (s at(i) asNumber) )
  168. )
  169. "The coefficents of quotient is " print
  170. for (i, 0, b size - 3,
  171.     (simplify(b at(i), 0) .. ", " ) print
  172. )
  173. simplify(b at(b size - 2), 0) print
  174. (", and the remainder is " .. simplify(b at(b size - 1), 0) .. ".") println
  175. "" println
  176. printSyntheticTable(a, c, s, b)
  177. "" println
  178. printDivisionResult(a, c, b)



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


실행> io testSyntheticDivision.io 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 대한민국 라이센스에 따라 이용하실 수 있습니다.