第3週の作業——1元の2次方程式の根を求めます


Description
式x 1=(-b+sqrt(b*b-4*a*c)/(2*a)、x 2=(-b-sqrt(b*b-4*a*c)/(2*a)を用いて、aが0に等しくない一元二次方程式ax 2+bx+c=0のルートを求める.
Input
方程式ax 2+bx+c=0の係数を表す3つの浮動小数点数a,b,c(それらの間に1つのスペースで区切られた)を含む行を入力します.
Output
方程式の解を表す行を出力します.
b 2=4*a*cの場合、2つの実根が等しい場合、出力形式はx 1=x 2=....b 2>4*a*cの場合、2つの実根が等しくない場合、出力形式はx 1=...;x2 = ...,ここでx 1>x 2.b 2<4*a*cの場合、2つの虚根がある場合、出力:x 1=実部+虚部i;x 2=実部-虚部i、すなわちx 1の虚部係数はx 2に等しい虚部係数より大きく、実部が0の場合は省略できない.実部=-b/(2*a)、虚部=sqrt(4*a*c-b*b)/(2*a)
すべての実数部分は小数点以下5桁まで正確で、数字、記号の間にスペースがありません.
Sample Input
    1
1.0 2.0 8.0

    2
1 0 1

 
Sample Output
    1
x1=-1.00000+2.64575i;x2=-1.00000-2.64575i

    2
x1=0.00000+1.00000i;x2=0.00000-1.00000i

 
Solution
#include 
#include 
#include 
using namespace std;
#define EPS 1e-7
int main()
{
	double a,b,c; //    float,    
	scanf("%lf%lf%lf",&a,&b,&c);
	double tmp = b*b - 4*a*c;
	if( tmp < EPS && tmp > - EPS)
		printf("x1=x2=%.5f",(-b)/(2*a)+EPS);  // + EPS        -0.00000 
	else if( tmp > EPS) {
		double x1 = (-b+sqrt(tmp))/(2*a);
		double x2 = (-b-sqrt(tmp))/(2*a)+EPS;
		if( x1 - x2 > EPS)
			printf("x1=%.5f;x2=%.5f",x1+EPS,x2+EPS);
		else
			printf("x1=%.5f;x2=%.5f",x2+EPS,x1+EPS);
	}
	else {
		printf("x1=%.5f+%.5fi;x2=%.5f-%.5fi",(-b)/(2*a)+EPS,sqrt(-tmp)/(2*a)+EPS,(-b)/(2*a)+EPS,sqrt(-tmp)/(2*a)+EPS);
	}
	return 0;
}

 
浮動小数点数の計算に関する問題は以下の点に注意しなければならない.
 
1)double、floatを使わないで、float精度が足りない
2)doubleタイプ変数は%lfで読み込まれ、%fではありません.出力double値は%f
3)a==bの方法で2つの浮動小数点数が等しいかどうかを判断しないでください.a==0の方法で浮動小数点数aが0に等しいかどうかを判断しないでください.浮動小数点数に誤差があるからです.a−b>−eps&&a−b4)-0.000のような出力を避けるために、出力する値に対して0に十分近いかどうかを判断し、そうであれば0.0を直接出力します.例えば、小数点以下のnビットを保持する場合、epsは10の−(n+1)次数をとり、数の絶対値がepsより小さいと判断した場合、0である
5)aは使わないほうがいい!=b a,bが等しいか否かを判断し,a>b,a