(2013)一元二次方程Ⅱ
Description
求一元二次方程
ax 2 +bx+c=0
的解。a,b,c为任意实数。
Input
输入数据有一行,包括a b c的值。
Output
按以下格式输出方程的根x1和x2。x1和x2之间有一个空格。 x1 x2
(1)如果x1和x2为实根,则以x1>=x2输出。
(2)如果方程是共轭复根,x1=m+ni,x2=m-ni,其中n>0。 其中x1, x2, m,n均保留2位小数。
Sample Input
1 2 3
Sample Output
-1.00+1.41i -1.00-1.41i
[参考解答]
#include <stdio.h>
#include <math.h>
int main ( )
{
float a,b,c,d,pr,pi,x1,x2;
scanf("%f %f %f",&a,&b,&c);
d=b*b-4*a*c;
if(d>=0)
{
x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
printf("%.2f %.2f\n",x1,x2);
}
else
{
pr=-b/(2*a);
pi=sqrt(-d)/(2*a);
printf("%.2f+%.2fi ",pr,pi);
printf("%.2f-%.2fi\n",pr,pi);
}
return 0;
}
完善:
以上结果提交OJ顺利通过,尽管自知对共轭复根处的处理有点太简单,但通过了,也乐得不追究了。
今天(2016年10月13日)上机课上,崔翔童鞋问我,题目中有“(2)如果方程是共轭复根……,其中n>0”,那个n>0怎么整,惊出一身冷汗:老贺想逃避,休想!
读上面的程序,其实可以看到,当a<0时,共轭复根的虚部pi<0,于是输出的结果,就会很难看。确切的说,是错的!
如下图:
这样的输出,太低级了。我们想要的是:
但是,最爱在输出格式上和人较劲的OJ,是怎么容忍这样的错误的?很简单,没有提供a<0时的测试数据,自然就让人能蒙混过关了。OJ啊,你那严格的名声来之不易,咋能不珍惜呢?
不管你OJ了,老贺决定认真点。你让人犯错,咱也不降低对自己的要求了。上代码:
#include <stdio.h>
#include <math.h>
int main ( )
{
float a,b,c,d,pr,pi,x1,x2;
scanf("%f %f %f",&a,&b,&c);
d=b*b-4*a*c;
if(d>=0)
{
x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
printf("%.2f %.2f\n",x1,x2);
}
else
{
pr=-b/(2*a);
pi=sqrt(-d)/(2*a);
if(a>0)
{
printf("%.2f+%.2fi ",pr,pi);
printf("%.2f-%.2fi\n",pr,pi);
}
else
{
printf("%.2f+%.2fi ",pr,-pi);
printf("%.2f-%.2fi\n",pr,-pi);
}
}
return 0;
}
其实,考虑共轭复根的对称性,可以如下省点代码(读起来难懂,就运行观察观察,再想想):
#include <stdio.h>
#include <math.h>
int main ( )
{
float a,b,c,d,pr,pi,x1,x2;
scanf("%f %f %f",&a,&b,&c);
d=b*b-4*a*c;
if(d>=0)
{
x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
printf("%.2f %.2f\n",x1,x2);
}
else
{
pr=-b/(2*a);
pi=sqrt(-d)/(2*a);
if(a<0) //这儿利用了共轭复根的对称性,反正输出那个形式就行
pi=-pi;
printf("%.2f+%.2fi ",pr,pi);
printf("%.2f-%.2fi\n",pr,pi);
}
return 0;
}