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

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

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

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

  1. /*
  2.  *  Filename: TestSyntheticMethod.cs
  3.  *
  4.  *  Purpose:  Find the quotient and remainder when some polynomial is
  5.  *            divided by a monic polynomial of the first degree.
  6.  *
  7.  *  Compile: csc TestSyntheticMethod.cs
  8.  *
  9.  *  Execute: TestSyntheticMethod -2 1 3 3 1
  10.  */
  11. using System;
  12. namespace MyTestApplication1 {
  13.     public class TestSyntheticMethod {
  14.         // 사용법 표시
  15.         public static void PrintUsage() {
  16.              Console.WriteLine("사용법: TestSyntheticMethod [수] [피제식의 계수들]");
  17.              Console.WriteLine("조립제법(synthetic method)에 의한 다항식 나눗셈 결과를 보여준다.");
  18.         }
  19.         // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  20.         public static string Simplify(double v) {
  21.             string t = "" + v;
  22.             if (t.EndsWith(".0"))
  23.                 t = t.Substring(0, t.Length - 2);
  24.             return t;
  25.         }
  26.         // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
  27.         // 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
  28.         public static string Simplify(double v, int width) {
  29.             string t = "" + v;
  30.             if (t.EndsWith(".0"))
  31.                 t = t.Substring(0, t.Length - 2);
  32.             int len = t.Length;
  33.             if (len < width)
  34.                 t = "               ".Substring(0, width - len) + t;
  35.             return t;
  36.         }
  37.         // 다항식을 내림차순의 스트링 표현으로 반환
  38.         public static string ToPolyString(double[] c) {
  39.             string t = "";
  40.             if (c.Length > 2) {
  41.                 if (Simplify(c[0]).Equals("1"))
  42.                     t += "x^" + (c.Length-1);
  43.                 else if (Simplify(c[0]).Equals("-1"))
  44.                     t += "-x^" + (c.Length-1);
  45.                 else
  46.                     t += Simplify(c[0]) + " x^" + (c.Length-1);
  47.             }
  48.             else if (c.Length == 2) {
  49.                 if (Simplify(c[0]).Equals("1"))
  50.                     t += "x";
  51.                 else if (Simplify(c[0]).Equals("-1"))
  52.                     t += "-x";
  53.                 else
  54.                     t += Simplify(c[0]) + " x";
  55.             }
  56.             else if (c.Length == 1) {
  57.                 t += Simplify(c[0]);
  58.             }
  59.             for (int i = 1; i < c.Length; i++) {
  60.                 if (c.Length - 1 - i > 1) {
  61.                     if (c[i] > 0.0) {
  62.                         if (Simplify(c[i]).Equals("1"))
  63.                             t += " + " + "x^" + (c.Length - 1 - i);
  64.                         else
  65.                             t += " + " + Simplify(c[i]) + " x^" + (c.Length - 1 - i);
  66.                     }
  67.                     else if (c[i] < 0.0) {
  68.                         if (Simplify(c[i]).Equals("-1"))
  69.                             t += " - " + "x^" + (c.Length - 1 - i);
  70.                         else
  71.                             t += " - " + Simplify(Math.Abs(c[i])) + " x^" + (c.Length - 1 - i);
  72.                     }
  73.                 }
  74.                 else if (c.Length - 1 - i == 1) {
  75.                     if (c[i] > 0.0) {
  76.                         if (Simplify(c[i]).Equals("1"))
  77.                             t += " + " + "x";
  78.                         else
  79.                             t += " + " + Simplify(c[i]) + " x";
  80.                 }
  81.                 else if (c[i] < 0.0) {
  82.                     if (Simplify(c[i]).Equals("-1"))
  83.                         t += " - " + "x";
  84.                     else
  85.                         t += " - " + Simplify(Math.Abs(c[i])) + " x";
  86.                 }
  87.             }
  88.             else if (c.Length - 1 - i == 0) {
  89.                if (c[i] > 0.0) {
  90.                     t += " + " + Simplify(c[i]);
  91.                 }
  92.                 else if (c[i] < 0.0)
  93.                     t += " - " + Simplify(Math.Abs(c[i]));
  94.                 }
  95.             }
  96.             return t;
  97.         }
  98.         // 다항식 나눗셈 결과를
  99.         //     (피제식) = (제식)(몫) + (나마지)
  100.         // 형태로 출력
  101.         public static void PrintDivisionResult(double a, double[] c, double[] b) {
  102.             Console.WriteLine("  " + ToPolyString(c));
  103.             Console.WriteLine();
  104.             Console.Write("    = ( " + ToPolyString( new double[] {1.0, -a} ) + " )");
  105.             double[] tmp = new double[b.Length - 1];
  106.             for (int i = 0; i < tmp.Length; i++) {
  107.                 tmp[i] = b[i];
  108.             }
  109.             Console.Write("( " + ToPolyString(tmp) + " )");
  110.             double r = b[b.Length - 1];
  111.             if (r > 0.0)
  112.                 Console.Write(" + " + Simplify(r));
  113.             else if (r < 0.0)
  114.                 Console.Write(" - " + Simplify(Math.Abs(r)));
  115.             Console.WriteLine();
  116.         }
  117.         // 조립제법 계산표 출력 메소드
  118.         public static void PrintSyntheticTable(double a, double[] c, double[] s, double[] q) {
  119.             Console.Write("       | ");
  120.             Console.Write(Simplify(c[0], 6));
  121.             for (int i = 1; i < c.Length; i++) {
  122.                 Console.Write("  " + Simplify(c[i], 6));
  123.             }
  124.             Console.WriteLine();
  125.             Console.Write(Simplify(a, 6) + " | ");
  126.             Console.Write("        ");
  127.             Console.Write(Simplify(s[1], 6));
  128.             for (int i = 2; i < s.Length; i++) {
  129.                 Console.Write("  " + Simplify(s[i], 6));
  130.             }
  131.             Console.WriteLine();
  132.             Console.Write("       |-");
  133.             for (int i = 0; i < q.Length; i++) {
  134.                 Console.Write("--------");
  135.             }
  136.             Console.WriteLine("");
  137.             Console.Write("         ");
  138.             Console.Write(Simplify(q[0], 6));
  139.             for (int i = 1; i < q.Length; i++) {
  140.                 Console.Write("  " + Simplify(q[i], 6));
  141.             }
  142.             Console.WriteLine();
  143.         }
  144.         // Java 언어의 main 메소드에 해당하는 C# 언어의 Main 메소드
  145.         public static void Main(String[] args) {
  146.             if (args.Length < 3) {
  147.                 PrintUsage();
  148.                 Environment.Exit(1);
  149.             }
  150.             //////////////////////////////////////////////////////
  151.             // 피제식은 c_0 x^n +  c_1 x^(n -1) + ... + c_n
  152.             // 제식은 x -  a
  153.             double a = Convert.ToDouble(args[0]);
  154.             double[] c = new double[args.Length - 1];
  155.             double[] s = new double[c.Length];
  156.             double[] b = new double[c.Length];
  157.             for (int i = 0; i < c.Length; i++) {
  158.                 c[i] = Convert.ToDouble(args[i + 1]);
  159.             }
  160.             //////////////////////////////////////////////////////
  161.             // 조립제법의 주요 부분
  162.             s[0] = 0.0;
  163.             b[0] = c[0];
  164.             for (int i = 1; i < c.Length; i++) {
  165.                 s[i] = b[i-1]*a;
  166.                 b[i] = c[i] + s[i];
  167.             }
  168.             //////////////////////////////////////////////////////
  169.             // 몫의 계수와 나머지를 출력한다.
  170.             Console.Write("몫의 계수는 ");
  171.             for (int i = 0; i < b.Length - 2; i++) {
  172.                 Console.Write(Simplify(b[i]) + ", " );
  173.             }
  174.             Console.Write(Simplify(b[b.Length - 2]));
  175.             Console.WriteLine(" 이고, 나머지는 " + Simplify(b[b.Length - 1]) + " 이다.");
  176.             Console.WriteLine();
  177.             //////////////////////////////////////////////////////
  178.             // 조립제법 표를 출력한다.
  179.             PrintSyntheticTable(a, c, s, b);
  180.             Console.WriteLine();
  181.             //////////////////////////////////////////////////////
  182.             // (피제식) = (제식) x (몫) + (나머지)
  183.             PrintDivisionResult(a, c, b);
  184.         }
  185.     }
  186. }





컴파일> csc TestSyntheticMethod.cs
실행> TestSyntheticMethod 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



Posted by Scripter
,