OpenJudge计算概论-求一元二次方程的根【含复数根的计算、浮点数与0的大小比较】

/*======================================================================
求一元二次方程的根
总时间限制: 1000ms 内存限制: 65536kB
描述
利用公式x1 = (-b + sqrt(b*b-4*a*c))/(2*a), x2 = (-b - sqrt(b*b-4*a*c))/(2*a)求一元二次方程ax^2 + bx + c =0的根,其中a不等于0。
输入
第一行是待解方程的数目n。 
其余n行每行含三个浮点数a, b, c(它们之间用空格隔开),分别表示方程ax2 + bx + c =0的系数。
输出
输出共有n行,每行是一个方程的根:
若是两个实根,则输出:x1=...;x2 = ...
若两个实根相等,则输出:x1=x2=...
若是两个虚根,则输出:x1=实部+虚部i; x2=实部-虚部i

所有实数部分要求精确到小数点后5位,数字、符号之间没有空格。
x1和x2的顺序:x1的实部>x2的实部||(x1的实部==x2的实部&&x1的虚部>=x2的虚部)
样例输入
3
1.0 3.0 1.0
2.0 -4.0 2.0
1.0 2.0 8.0
样例输出
x1=-0.38197;x2=-2.61803
x1=x2=1.00000
x1=-1.00000+2.64575i;x2=-1.00000-2.64575i
提示
1、需要严格按照题目描述的顺序求解x1、x2。
2、方程的根以及其它中间变量用double类型变量表示。
3、函数sqrt()在头文件math.h中。
4、要输出浮点数、双精度数小数点后5位数字,可以用下面这种形式: 

printf("%.5f", num);

注意,在使用Java做此题时,可能会出现x1或x2等于-0的情形,此时,需要把负号去掉
========================================================================*/
 1 #include<stdio.h>
 2 #include<math.h>
 3 int comparToZero(double x);//当x与0之差的绝对值小于0.00001(即:1e-5)时 认为x等于0 
 4 int main()
 5 {
 6     int n,i;
 7     double a,b,c,delt;
 8     double x1,x2,real,image;
 9     freopen("222.in","r",stdin);
10     scanf("%d",&n);
11     for(i=0;i<n;i++)
12     {
13         scanf("%lf%lf%lf",&a,&b,&c);
14         delt=b*b-4*a*c;
15         if(comparToZero(delt)==1)   //if(delt>0)
16         {
17             x1=(-b+sqrt(delt))/2/a;
18             x2=(-b-sqrt(delt))/2/a;
19             if(comparToZero(x1)==0)
20                 x1=0;
21             if(comparToZero(x2)==0)
22                 x2=0;
23             printf("x1=%.5lf;x2=%.5lf
",x1,x2);
24         }
25         else if(comparToZero(delt)==0)   //if(delt==0)
26         {
27             x1=-b/2/a;
28             if(comparToZero(x1)==0)
29                 x1=0;
30             printf("x1=x2=%.5lf
",x1);
31         }
32         else   //delt<0
33         {
34             delt=sqrt(-delt);
35             real=-b/2/a;
36             image=delt/2/a;
37             if(comparToZero(real)==0) real=0;
38             if(comparToZero(image)==0) image==0;
39             printf("x1=%.5lf+%.5lfi;x2=%.5lf-%.5lfi
",real,image,real,image);
40         }
41     }
42     return 0;
43 }
44 int comparToZero(double x)//当x与0之差的绝对值小于0.00001(即:1e-5)时 认为x等于0 
45 {
46     /*if(x>0)  return 1;
47     else if(x<0)  return -1;
48     else  return 0;*/  
49     //上面的写法会出现浮点数计算精度的误差 。需要改用下面的方法来比较浮点数x和0之间的大小关系。 
50     if((x-0)>1e-5) return 1;
51     else if((x-0)<-(1e-5)) return -1;
52     else return 0;
53 }
54 /*==============================================================================
55 实数运算中,经常需要判断实数x和y是否相等。编程者往往把判断的条件简单设成x==y或者y-x==0.
56 实际上,这种写法是有失偏颇的,可能会产生精度误差。
57 避免精度误差的办法就是设置一个精度常量delta。
58 若y-x的实数值与0之间的区间长度小于delta,则认为x和y相等,这样就可以把误差控制在delta范围内。
59 显然,判断实数x和y是否相等的条件应设成|x-y|<=delta。下面是一个实例。
60 ===============================================================================*/

这个题目需要注意的两个地方:

/*==========================================
这个题需要注意的地方:
1. 当一个数如果在(-0.000005,0)之间,输出精确到小数点后5位,
就是0而不是期望的某个小数0.00……,所以需要判断处理一下输出数据

2. 浮点数无法和0比较,浮点数本身不是一个精确值,
可以用fabs(x-0)<1e-5来比较(这里精确度为5)
============================================*/

原文地址:https://www.cnblogs.com/huashanqingzhu/p/3462619.html