다항식 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 )
- /*
- * Filename: testSyntheticDivision.go
- *
- * Purpose: Find the quotient and remainder when some polynomial is
- * divided by a monic linear polynomial.
- *
- * Execute: go run testSyntheticDivision.go -2 1 3 3 1
- *
- * or
- *
- * Compile: go build testSyntheticDivision.go
- * Execute: ./testSyntheticDivision -2 1 3 3 1
- */
- package main
- import (
- "fmt"
- "os"
- "strconv"
- "math"
- )
- func print(str string) {
- fmt.Printf("%s", str);
- }
- func println(str string) {
- fmt.Printf("%s\n", str);
- }
- // 사용법 표시
- func printUsage() {
- /// println("사용법: testSyntheticDivision [수] [피제식의 계수들]");
- /// println("조립제법(synthetic method)에 의한 다항식 나눗셈 결과를 보여준다.");
- println("Usage: testSyntheticDivision [number] [coefficients of dividend]");
- println("Show the result of synthetic division.");
- }
- // 부동소수점수의 표현이 .0 으로 끝나는 경우 이를 잘라낸다.
- // 전체 문자열 표시 너비는 매개변수 width 로 전달받아 처리한다.
- func simplify(v float64, width int) string {
- var n int
- var slen int
- var t string = " ";
- var tmp string = " ";
- t = fmt.Sprintf("%g", v);
- n = len(t);
- if (n > 2) && (t[n - 2] == '.') && (t[n - 1] == '0') {
- t = t[0:n-2]
- }
- slen = len(t);
- tmp = t
- if (slen < width) {
- t = " "
- t = t[0:width - slen]
- t = t + tmp
- }
- return t
- }
- // 다항식을 내림차순의 문자열로로 반환하는 함수
- func toPolyString(c []float64, size int) string {
- var SIZE int = size;
- var i int;
- var t string = ""
- var tmp string
- var pc string = simplify(c[0], -1);
- var pci string
- if SIZE > 2 {
if (len(pc) == 1 && pc[0] == '1') { - t = fmt.Sprintf("x^%d", SIZE - 1);
- } else if (len(pc) == 2 && pc[0] == '-' && pc[1] == '1') {
- t = fmt.Sprintf("-x^%d", SIZE - 1);
- } else {
- t = fmt.Sprintf("%s x^%d", simplify(c[0], -1), SIZE - 1);
- }
- } else if SIZE == 2 {
- if (len(pc) == 1 && pc[0] == '1') {
- t = "x"
- } else if (len(pc) == 2 && pc[0] == '-' && pc[1] == '1') {
- t = "-x"
- } else {
- t = fmt.Sprintf("%s x", simplify(c[0], -1));
- }
- } else if SIZE == 1 {
- t = fmt.Sprintf("%s", simplify(c[0], -1));
- }
- for i = 1; i < SIZE; i++ {
- pci = simplify(c[i], -1);
- if SIZE - 1 - i > 1 {
- if c[i] > 0.0 {
- if len(pci) == 1 && pci[0] == '1' {
- tmp = fmt.Sprintf(" + x^%d", SIZE - 1 - i);
- t += tmp
- } else {
- tmp = fmt.Sprintf(" + %s x^%d", simplify(c[i], -1), SIZE - 1 - i);
- t += tmp
- }
- } else if c[i] < 0.0 {
- if len(pci) == 2 && pci[0] == '-' && pci[1] == '1' {
- tmp = fmt.Sprintf(" - x^%d", SIZE - 1 - i);
- t += tmp
- } else {
- tmp = fmt.Sprintf(" - %s x^%d", simplify(math.Abs(c[i]), -1), SIZE - 1 - i);
- t += tmp
- }
- }
- } else if SIZE - 1 - i == 1 {
- if c[i] > 0.0 {
- if len(pci) == 1 && pci[0] == '1' {
- t += " + x"
- } else {
- tmp = fmt.Sprintf(" + %s x", simplify(c[i], -1));
- t += tmp
- }
- } else if c[i] < 0.0 {
- if len(pci) == 2 && pci[0] == '-' && pci[1] == '1' {
- t += " - x"
- } else {
- tmp = fmt.Sprintf(" - %s x", simplify(math.Abs(c[i]), -1));
- t += tmp
- }
- }
- } else if SIZE - 1 - i == 0 {
- if c[i] > 0.0 {
- tmp = fmt.Sprintf(" + %s", simplify(c[i], -1));
- t += tmp
- } else if (c[i] < 0.0) {
- tmp = fmt.Sprintf(" - %s", simplify(math.Abs(c[i]), -1));
- t += tmp
- }
- }
- }
- return t
- }
- // 다향식 나눗셈 결과를
- // (피제식) = (제식)(몫) + (나마지)
- // 형태로 출력
- func printDivisionResult(a float64, c []float64, b []float64, size int) {
- var SIZE int = size;
- var i int
- var r float64
- var monic []float64 = []float64 { 1.0, 0.0 };
- print(" ");
- print(toPolyString(c, SIZE));
- println("");
- print(" = ( ");
- monic[1] = -a;
- print(toPolyString( monic, 2 ));
- print(" )")
- var pTmpPoly []float64 = make([]float64, SIZE);
- for i = 0; i < SIZE - 1; i++ {
- pTmpPoly[i] = b[i];
- }
- print("( ");
- print(toPolyString(pTmpPoly, SIZE - 1));
- print(" )");
- r = b[SIZE - 1];
- if r > 0.0 {
- print(" + ");
- print(simplify(r, -1));
- } else if (r < 0.0) {
- print(" - ");
- print(simplify(math.Abs(r), -1));
- }
- println("");
- }
- // 조립제법 계산표 출력 함수
- func printSyntheticTable(a float64, c []float64, s []float64, q []float64, size int) {
- var SIZE int = size;
- var i int
- print(" | ");
- print(simplify(c[0], 6));
- for i = 1; i < SIZE; i++ {
- print(" ");
- print(simplify(c[i], 6));
- }
- println("");
- print(simplify(a, 6));
- print(" | ");
- print(" ");
- print(simplify(s[1], 6));
- for i = 2; i < SIZE; i++ {
- print(" ");
- print(simplify(s[i], 6));
- }
- println("");
- print(" |-");
- for i = 0; i < SIZE; i++ {
- print("--------");
- }
- println("");
- print(" ");
- print(simplify(q[0], 6));
- for i = 1; i < SIZE; i++ {
- print(" ");
- print(simplify(q[i], 6));
- }
- println("");
- }
- // Go 언어 프로그램의 실행 시작 지점
- func main() {
- var i int
- var SIZE = len(os.Args) - 2
- var a float64
- var c []float64 = make([]float64, SIZE + 2)
- var s []float64 = make([]float64, SIZE + 2)
- var b []float64 = make([]float64, SIZE + 2)
- if len(os.Args) < 4 {
- printUsage()
- return
- }
- //////////////////////////////////////////////////////
- // 피제식은 c_0 x^n + c_1 x^(n -1) + ... + c_n
- // 제식은 x - a
- a, _ = strconv.ParseFloat(os.Args[1], 64)
- for i = 0; i < SIZE; i++ {
- c[i], _ = strconv.ParseFloat(os.Args[i + 2], 64)
- }
- //////////////////////////////////////////////////////
- // 조립제법의 주요 부분
- s[0] = 0.0;
- b[0] = c[0];
- for i = 1; i < SIZE; i++ {
- s[i] = b[i-1]*a;
- b[i] = c[i] + s[i];
- }
- //////////////////////////////////////////////////////
- // 몫의 계수와 나머지를 출력한다.
- /// print("몫의 계수는 ");
- print("The coefficients of the quotient are ");
- for i = 0; i < SIZE - 2; i++ {
- print(simplify(b[i], -1));
- print(", ");
- }
- print(simplify(b[SIZE - 2], -1));
- // print(" 이고, 나머지는 ");
- print("\nand the remainder is ");
- print(simplify(b[SIZE - 1], -1));
- /// println(" 이다.");
- println(".");
- println("");
- //////////////////////////////////////////////////////
- // 조립제법 표를 출력한다.
- printSyntheticTable(a, c, s, b, SIZE);
- println("");
- //////////////////////////////////////////////////////
- // (피제식) = (제식) x (몫) + (나머지)
- printDivisionResult(a, c, b, SIZE);
- }
실행> 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
'프로그래밍 > Go' 카테고리의 다른 글
Go 프로그램 언어로 긴 자리 정수 계산하기 (0) | 2012.06.18 |
---|---|
현재 시각 알아내기 with Go (0) | 2012.06.17 |
80컬럼 컨솔에 19단표 출력하기 예제 with Go (0) | 2012.06.16 |
(최대공약수 구하기) while... 반복문 예제 with Go (0) | 2012.06.15 |
if...else... 조건문 사용 예제 with Go (0) | 2012.06.15 |