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

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

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

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


아래의 소스파일은 go run 명령을 사용하면 컴파일 과정 없이 그대로 실행된다.
(실행 예:  go run testSyntheticDivision.go 1 2 3 4 5  )


  1. /*
  2.  *  Filename: testSyntheticDivision.go
  3.  *
  4.  *  Purpose:  Find the quotient and remainder when some polynomial is
  5.  *            divided by a monic linear polynomial.
  6.  *
  7.  *  Execute:  go run testSyntheticDivision.go -2 1 3 3 1
  8.  *
  9.  *  or
  10.  *
  11.  *  Compile:  go build testSyntheticDivision.go
  12.  *  Execute:  ./testSyntheticDivision -2 1 3 3 1
  13.  */
  14. package main
  15. import (
  16.     "fmt"
  17.     "os"
  18.     "strconv"
  19.     "math"
  20. )
  21. func print(str string) {
  22.     fmt.Printf("%s", str);
  23. }
  24. func println(str string) {
  25.     fmt.Printf("%s\n", str);
  26. }
  27. // 사용법 표시
  28. func printUsage() {
  29.      /// println("사용법: testSyntheticDivision [수] [피제식의 계수들]");
  30.      /// println("조립제법(synthetic method)에 의한 다항식 나눗셈 결과를 보여준다.");
  31.      println("Usage: testSyntheticDivision [number] [coefficients of dividend]");
  32.      println("Show the result of synthetic division.");
  33. }
  34. // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  35. // 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  36. func simplify(v float64, width int) string {
  37.     var n int
  38.     var slen int
  39.     var t string = "                               ";
  40.     var tmp string = "                               ";
  41.     t = fmt.Sprintf("%g", v);
  42.     n = len(t);
  43.     if (n > 2) && (t[n - 2] == '.') && (t[n - 1] == '0') {
  44.         t = t[0:n-2]
  45.     }
  46.     slen = len(t);
  47.     tmp =  t
  48.     if (slen < width) {
  49.         t = "               "
  50.         t = t[0:width - slen]
  51.         t = t + tmp
  52.     }
  53.     return t
  54. }
  55. // 다항식을 내림차순의 문자열로로 반환하는 함수
  56. func toPolyString(c []float64, size int) string {
  57.     var SIZE int = size;
  58.     var i int;
  59.     var t string = ""
  60.     var tmp string
  61.     var pc string = simplify(c[0], -1);
  62.     var pci string
  63.     if SIZE > 2 {
            if (len(pc) == 1 && pc[0] == '1') {
  64.             t = fmt.Sprintf("x^%d", SIZE - 1);
  65.         } else if (len(pc) == 2 && pc[0] == '-' && pc[1] == '1') {
  66.             t = fmt.Sprintf("-x^%d", SIZE - 1);
  67.         } else {
  68.             t = fmt.Sprintf("%s x^%d", simplify(c[0], -1), SIZE - 1);
  69.         }
  70.     } else if SIZE == 2 {
  71.         if (len(pc) == 1 && pc[0] == '1') {
  72.             t = "x"
  73.         } else if (len(pc) == 2 && pc[0] == '-' && pc[1] == '1') {
  74.             t = "-x"
  75.         } else {
  76.             t = fmt.Sprintf("%s x", simplify(c[0], -1));
  77.         }
  78.     } else if SIZE == 1 {
  79.         t = fmt.Sprintf("%s", simplify(c[0], -1));
  80.     }
  81.     for i = 1; i < SIZE; i++ {
  82.         pci = simplify(c[i], -1);
  83.         if SIZE - 1 - i > 1 {
  84.             if c[i] > 0.0 {
  85.                 if len(pci) == 1 && pci[0] == '1' {
  86.                     tmp = fmt.Sprintf(" + x^%d", SIZE - 1 - i);
  87.                     t += tmp
  88.                 } else {
  89.                     tmp = fmt.Sprintf(" + %s x^%d", simplify(c[i], -1), SIZE - 1 - i);
  90.                     t += tmp
  91.                 }
  92.             } else if c[i] < 0.0 {
  93.                 if len(pci) == 2 && pci[0] == '-' && pci[1] == '1' {
  94.                     tmp = fmt.Sprintf(" - x^%d", SIZE - 1 - i);
  95.                     t += tmp
  96.                 } else {
  97.                     tmp = fmt.Sprintf(" - %s x^%d", simplify(math.Abs(c[i]), -1), SIZE - 1 - i);
  98.                     t += tmp
  99.                 }
  100.             }
  101.         } else if SIZE - 1 - i == 1 {
  102.             if c[i] > 0.0 {
  103.                 if len(pci) == 1 && pci[0] == '1' {
  104.                     t += " + x"
  105.                 } else {
  106.                     tmp = fmt.Sprintf(" + %s x", simplify(c[i], -1));
  107.                     t += tmp
  108.                 }
  109.             } else if c[i] < 0.0 {
  110.                 if len(pci) == 2 && pci[0] == '-' && pci[1] == '1' {
  111.                     t += " - x"
  112.                 } else {
  113.                     tmp = fmt.Sprintf(" - %s x", simplify(math.Abs(c[i]), -1));
  114.                     t += tmp
  115.                 }
  116.             }
  117.         } else if SIZE - 1 - i == 0 {
  118.             if c[i] > 0.0 {
  119.                 tmp = fmt.Sprintf(" + %s", simplify(c[i], -1));
  120.                 t += tmp
  121.             } else if (c[i] < 0.0) {
  122.                 tmp = fmt.Sprintf(" - %s", simplify(math.Abs(c[i]), -1));
  123.                 t += tmp
  124.             }
  125.         }
  126.     }
  127.     return t
  128. }
  129. // 다향식 나눗셈 결과를
  130. //     (피제식) = (제식)(몫) + (나마지)
  131. // 형태로 출력
  132. func printDivisionResult(a float64, c []float64, b []float64, size int) {
  133.     var SIZE int = size;
  134.     var i int
  135.     var r float64
  136.     var monic []float64 = []float64 { 1.0, 0.0 };
  137.     print("  ");
  138.     print(toPolyString(c, SIZE));
  139.     println("");
  140.     print("    = ( ");
  141.     monic[1] = -a;
  142.     print(toPolyString(  monic, 2 ));
  143.     print(" )")
  144.     var pTmpPoly []float64 = make([]float64, SIZE);
  145.     for i = 0; i < SIZE - 1; i++ {
  146.         pTmpPoly[i] = b[i];
  147.     }
  148.     print("( ");
  149.     print(toPolyString(pTmpPoly, SIZE - 1));
  150.     print(" )");
  151.     r = b[SIZE - 1];
  152.     if r > 0.0 {
  153.         print(" + ");
  154.         print(simplify(r, -1));
  155.     } else if (r < 0.0) {
  156.         print(" - ");
  157.         print(simplify(math.Abs(r), -1));
  158.     }
  159.     println("");
  160. }
  161. // 조립제법 계산표 출력 함수
  162. func printSyntheticTable(a float64, c []float64, s []float64, q []float64, size int) {
  163.     var SIZE int = size;
  164.     var i int
  165.     print("       | ");
  166.     print(simplify(c[0], 6));
  167.     for i = 1; i < SIZE; i++ {
  168.         print("  ");
  169.         print(simplify(c[i], 6));
  170.     }
  171.     println("");
  172.     print(simplify(a, 6));
  173.     print(" | "); 
  174.    print("        ");
  175.     print(simplify(s[1], 6));
  176.     for i = 2; i < SIZE; i++ {
  177.         print("  ");
  178.         print(simplify(s[i], 6));
  179.     }
  180.     println("");
  181.     print("       |-");
  182.     for i = 0; i < SIZE; i++ {
  183.         print("--------");
  184.     }
  185.     println("");
  186.     print("         ");
  187.     print(simplify(q[0], 6));
  188.     for i = 1; i < SIZE; i++ {
  189.         print("  ");
  190.         print(simplify(q[i], 6));
  191.     }
  192.     println("");
  193. }
  194. // Go 언어 프로그램의 실행 시작 지점
  195. func main() {
  196.     var i int
  197.     var SIZE = len(os.Args) - 2
  198.     var a float64
  199.     var c []float64 = make([]float64, SIZE + 2)
  200.     var s []float64 = make([]float64, SIZE + 2)
  201.     var b []float64 = make([]float64, SIZE + 2)
  202.     if len(os.Args) < 4 {
  203.         printUsage()
  204.         return
  205.     }
  206.     //////////////////////////////////////////////////////
  207.     // 피제식은 c_0 x^n +  c_1 x^(n -1) + ... + c_n
  208.     // 제식은 x -  a
  209.     a, _ = strconv.ParseFloat(os.Args[1], 64)
  210.     for i = 0; i < SIZE; i++ {
  211.         c[i], _ = strconv.ParseFloat(os.Args[i + 2], 64)
  212.     }
  213.     //////////////////////////////////////////////////////
  214.     // 조립제법의 주요 부분
  215.     s[0] = 0.0;
  216.     b[0] = c[0];
  217.     for i = 1; i < SIZE; i++ {
  218.         s[i] = b[i-1]*a;
  219.         b[i] = c[i] + s[i];
  220.     }
  221.     //////////////////////////////////////////////////////
  222.     // 몫의 계수와 나머지를 출력한다.
  223.     /// print("몫의 계수는 ");
  224.     print("The coefficients of the quotient are ");
  225.     for i = 0; i < SIZE - 2; i++ {
  226.         print(simplify(b[i], -1));
  227.         print(", ");
  228.     }
  229.     print(simplify(b[SIZE - 2], -1));
  230.     // print(" 이고, 나머지는 ");
  231.     print("\nand the remainder is ");
  232.     print(simplify(b[SIZE - 1], -1));
  233.     /// println(" 이다.");
  234.     println(".");
  235.     println("");
  236.     //////////////////////////////////////////////////////
  237.     // 조립제법 표를 출력한다.
  238.     printSyntheticTable(a, c, s, b, SIZE);
  239.     println("");
  240.     //////////////////////////////////////////////////////
  241.     // (피제식) = (제식) x (몫) + (나머지)
  242.     printDivisionResult(a, c, b, SIZE);
  243. }




실행> go run testSyntheticDivision.go 1 2 3 4 5
The coefficients of the quotient are 2, 5, 9
and the remainder is 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

 

또는

 

컴파일> go build testSyntheticDivision.go

실행> ./testSyntheticDivision 1 2 3 4 5
The coefficients of the quotient are 2, 5, 9
and the remainder is 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
,