Problem L: 求一元二次方程的根

求一元二次方程的根

一元二次方程的标准形式为ax2+bx+c=0(a≠0),其中a、b、c为常数。求解一元二次方程的根x时有三种情况,分别为(记Δ=b2-4ac):

  1. Δ>0,有两个不等的实根;
  2. Δ=0,有两个相同的实根;
  3. Δ<0,有两个共轭的虚根。

Input

输入为多行,每行为一元二次方程的三个常数a,b,c,在double类型范围之内。当输入的a为0时,表示输入结束。

Output

每行输入的样例对应三行输出。

第一行输出为样例的编号。

第二行输出为所输入常数a,b,c对应的一元二次方程的标准形式,要求输出满足a>0。

第三行输出为所输入方程的根,分为三种情况:

  1. 若方程满足Δ>0,即有两不等实根x1、x2,则按顺序(先小后大)输出这两个实根。

  2. 若方程满足Δ=0,即有两相同实根x,则输出一个实根。

  3. 若方程满足Δ<0,即有两共轭的虚根x1、x2,则输出两个虚根,虚部符号为正的(即u+vi形式)先输出,虚部符号为负的(x-yi形式)后输出。

以上输出均不输出数学上无意义或可省略的的符号,所有数值最多保留6位有效数字。每个样例之后都有一个空行分隔。

Sample Input

1 2 1
-1 2 -1
-5 2 -0.2
-3 2 0
3 0 12
2 4 4
0
Sample Output

Case 1 :
x^2 + 2x + 1 = 0
only one real root : -1

Case 2 :
x^2 - 2x + 1 = 0
only one real root : 1

Case 3 :
5x^2 - 2x + 0.2 = 0
only one real root : 0.2

Case 4 :
3x^2 - 2x = 0
two real roots : 0, 0.666667

Case 5 :
3x^2 + 12 = 0
two imaginary roots : 2i, -2i

Case 6 :
2x^2 + 4x + 4 = 0
two imaginary roots : -1+i, -1-i

HINT

输出方程格式的各种情况要想清楚,这一部分测试数据给的很全面。另一个就是浮点数的精度控制,这一部分sample给出了例子。

值得注意的是,linux下gcc编译的浮点数运算结果有-0,这是OJ系统Judge端使用的系统;而windows XP下的minGW编译器和VC6不会产生-0,只会输出0;但windows 7下的minGW编译器是能够产生-0的(确实很诡异)。因此使用windows XP的同学忽略了对结果为0的检测,程序需要对结果为0的情况进行全面考虑,确保正确的输出0。这个问题卡了好些同学好几天。

关于是否会产生-0,输出表达式0.0/-1的结果就能测试出来。浮点数从负数方向运算出结果为0,则浮点值为-0是符合C语言浮点数运算规则的,目前尚不清楚windows XP系统不能产生-0的原因。

#include<stdio.h>  
#include<math.h>  
int main()  
{  
    double a, b, c, dt;  
    int case_ = 0;  
    while(scanf("%lf", &a) == 1&& fabs(a) > 0.0000001)  
    {  
        scanf("%lf%lf", &b, &c);  
        if(a < -0.0000001)  
        {  
            a = -a;  
            b = -b;  
            c = -c;  
        }  
        if(case_)  
            printf("\n");  
        ++case_;  
        printf("Case %d :\n", case_);  
        (a == 1)?printf("x^2"):printf("%lgx^2", a);  
        if(fabs(b) < 0.0000001);  
        else if(b < -0.0000001&& fabs(fabs(b) - 1)> 0.0000001)  
            printf(" - %lgx", fabs(b));  
        else if(b > 0.0000001&& fabs(fabs(b) - 1)> 0.0000001)  
            printf(" + %lgx", fabs(b));  
        else if(b < 0.0000001&& fabs(fabs(b) - 1)< 0.0000001)  
            printf(" - x");  
        else if(b > 0.0000001&& fabs(fabs(b) - 1)< 0.0000001)  
            printf(" + x");  
        if(fabs(c) < 0.0000001);  
        else if(c > 0.0000001)  
            printf(" + %lg", c);  
        else if(c < -0.0000001)  
            printf(" - %lg", fabs(c));  
        printf(" = 0\n");  
        double x1, x2, temp;  
        dt = b * b - 4 * a * c;  
        if(dt > 0.0000001)  
        {  
            x1 = (- b - sqrt(dt)) / (2 * a);  
            x2 = (- b + sqrt(dt)) / (2 * a);  
            if(x1 - x2 > 0.0000001)  
            {  
                temp = x1;  
                x1 = x2;  
                x2 = temp;  
            }  
            if(fabs(x1) < 0.0000001)  
                x1 = 0;  
            if(fabs(x2) < 0.0000001)  
                x2 = 0;  
            printf("two real roots : %lg, %lg\n", x1, x2);  
        }  
        if(fabs(dt) < 0.0000001)  
            {  
                x1 =  (-b) / (2 * a);  
                if(fabs(x1) < 0.0000001)  
                    x1 = 0;  
                printf("only one real root : %lg\n", x1);  
            }  
        if(dt < -0.0000001)  
        {  
            if((-b / (2 * a)) == 0&& (fabs(sqrt(4 * a * c-b * b) / (2 * a) - 1 ) > 0.0000001))  
                {  
                    printf("two imaginary roots : %lgi, ", sqrt(4 * a * c-b * b) / (2 * a));  
                    printf("-%lgi\n", sqrt(4 * a * c-b * b) / (2 * a));  
                }  
            else if((-b / (2 * a)) == 0&& (fabs(sqrt(4 * a * c-b * b) / (2 * a) - 1 ) < 0.0000001))  
                {  
                    printf("two imaginary roots : i, ");  
                    printf("-i\n");  
                }  
            else if(fabs(sqrt(4 * a * c-b * b) / (2 * a) - 1 ) < 0.0000001)  
            {  
                printf("two imaginary roots : %lg+i, ", (-b / (2 * a)));  
                printf("%lg-i\n", (-b / (2 * a)));  
            }  
            else  
            {  
                printf("two imaginary roots : %lg+%lgi, ", (-b / (2 * a)), sqrt(4 * a * c-b * b) / (2 * a));  
                printf("%lg-%lgi\n", (-b / (2 * a)), sqrt(4 * a * c-b * b) / (2 * a));  
            }  
        }  
    }  
    return 0;  
}  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值