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\n",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\n",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\n",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)
============================================*/