next up previous
Next: 実習 2: Up: 実習 2: 2次方程式の解 Previous: 補足 fprintf

このプログラムの問題点

ファイル 5-2.c をコンパイルして実行ファイルを作って下さい. sqrt を使っていますから, オプション -lm を忘れないようにして下さい.

e023199@cc> gcc 5-2.c -lm
e023199@cc> ./a.out 
Input the coefficients >> 1 3 2
The roots are -1.000000 and -2.000000

$x^2+3x+2=0$の様な簡単な方程式では, 正確な解が求まります. では, $0.1 x^2 + 10000.0001x +10 = 0$ ではどうでしょうか. 数学的には, $-0.001$$-100000$ が解です. 私の環境では次のようになりました.

e023199@cc> ./a.out
IInput the coefficients >> 0.1 10000.0001 10
The roots are -0.00100000000202272 and -100000.00000000000000000

小さいながらも, 真の解と計算機の結果に誤差が現れます. この場合 $\vert b\vert$ $\sqrt{b^2-4ac}$ の差が小さいため, 解の公式の分子の 計算部分で丸め誤差がでています. これを避けるためには, 分子の値が大きい方は そのまま計算し, 小さい方は解と係数の関係から求める計算をします. そのようにして書いたプログラムが次です. 私の環境では誤差がでなくなります.

/* File name 5-3.c */

#include <stdio.h>
#include <math.h>
#define BUFFSIZE 1024

main()
{
        double a, b, c;
        double det;
        double ans1, ans2;
        char input[BUFFSIZE];

        printf("Input the coefficients >> ");

        fgets(input, BUFFSIZE, stdin);
        sscanf(input, "%lf %lf %lf", &a, &b, &c);

        if (a==0){
                fprintf(stderr, "a=0 does not make a quadratic equation.\n");
                exit(1);
        }

        det = b*b-4*a*c;

        if (det < 0.0){
                fprintf(stdout,"The equation has imaginary roots\n");
                exit(1);
        }

        else if (det==0.0){
                printf("The root is %f\n", -b/(2.0*a));
                return(0);
        }

        else if (b >=0) {
                ans1= (-b-sqrt(det))/(2.0*a);
                ans2= c/(a*ans1);
                printf("The roots are %17.16f and %17.16f\n", ans1, ans2);
        }

        else {
                ans1= (-b+sqrt(det))/(2.0*a);
                ans2= c/(a*ans1);
                printf("The roots are %17.16f and %17.16f\n", ans1, ans2);
        }
}



Next: 実習 2: Up: 実習 2: 2次方程式の解 Previous: 補足 fprintf