大神们来刷道简单的OJ题吧

A1726542850 2015-11-23 11:01:09
Problem C: 求一元二次方程的根
Time Limit: 1 Sec Memory Limit: 2 MB
Submit: 6375 Solved: 986
[Submit][Status][Web Board]
Description

一元二次方程的标准形式为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<stdlib.h>
#include<math.h>
#define X 0.000001
int i=1;
int main()
{
double a,b,c;
double t,t1,x1,x2,x3;
while(1)
{
scanf("%lf",&a);
if(fabs(a)<X) break;
else
{ scanf("%lf%lf",&b,&c);
t=b*b-4*a*c;
t1=sqrt(fabs(b*b-4*a*c));
x1=-t1/(2*a);
x2=+t1/(2*a);
x3=-b/(2*a);
if(fabs(fabs(a)-1)<X)printf("Case %d :\nx^2",i);
else printf("Case %d :\n%gx^2",i,fabs(a));
if(fabs(fabs(b)-1)>X)
{if(a>X)
{
if(b>X) printf(" + %gx",b);
else if(fabs(b)<X) ;
else printf(" - %gx",-b);
if(c>X) printf(" + %g = 0\n",c);
else if(fabs(c)<X) printf(" = 0\n");
else printf(" - %g = 0\n",-c);
}
if(a<X)
{
if(b>X) printf(" - %gx",b);
else if(fabs(b)<X) ;
else printf(" + %gx",-b);
if(c>X) printf(" - %g = 0\n",c);
else if(fabs(c)<X) printf(" = 0\n");
else printf(" + %g = 0\n",-c);
}
}
if(fabs(b-1)<X){if(a>X)
{
if(b>X) printf(" + x");
else if(fabs(b)<X) ;
else printf(" - x");
if(c>X) printf(" + %g = 0\n",c);
else if(fabs(c)<X) printf(" = 0\n");
else printf(" - %g = 0\n",-c);
}
if(a<X)
{
if(b>X) printf(" - x");
else if(fabs(b)<X) ;
else printf(" + x");
if(c>X) printf(" - %g = 0\n",c);
else if(fabs(c)<X) printf(" = 0\n");
else printf(" + %g = 0\n",-c);
}
}
if(fabs(b+1)<X)
{if(a>X)
{
if(b>X) printf(" + x");
else if(fabs(b)<X) ;
else printf(" - x");
if(c>X) printf(" + %g = 0\n",c);
else if(fabs(c)<X) printf(" = 0\n");
else printf(" - %g = 0\n",-c);
}
if(a<X)
{
if(b>X) printf(" - x");
else if(fabs(b)<X) ;
else printf(" + x");
if(c>X) printf(" - %g = 0\n",c);
else if(fabs(c)<X) printf(" = 0\n");
else printf(" + %g = 0\n",-c);
}
}
if(t>X)printf("two real roots : %g, %g\n\n",x3+x2,x3+x1);
if(fabs(t)<X){if(fabs(x1+x3)<X)printf("only one real root : 0\n\n");else printf("only one real root : %g\n\n",x1+x3);}
if(t<-X)
{
printf("two imaginary roots : ");
if(fabs(x3)<X&&x2>X&&fabs(x2-1)>X) printf("%gi, ",x2);
if(fabs(x3)<X&&x2>X&&fabs(x2-1)<X) printf("i, ");
if(fabs(x3)<X&&x2<-X&&fabs(x2+1)>X) printf("%gi, ",x2);
if(fabs(x3)<X&&x2<-X&&fabs(x2+1)<X) printf("-i, ");

if(fabs(x3)>X&&x2<-X&&fabs(x2+1)>X) printf("%g-%gi, ",x3,fabs(x2));
if(fabs(x3)>X&&x2<-X&&fabs(x2+1)<X) printf("%g-i, ",x3,fabs(x2));
if(fabs(x3)>X&&x2>X&&fabs(x2-1)<X) printf("%g+i, ",x3,x2);
if(fabs(x3)>X&&x2>X&&fabs(x2-1)>X) printf("%g+%gi, ",x3,x2);
/* second */
if(fabs(x3)<X&&x1>X&&fabs(x1-1)>X) printf("%gi\n\n",x1);
if(fabs(x3)<X&&x1>X&&fabs(x1-1)<X) printf("i\n\n");
if(fabs(x3)<X&&x1<-X&&fabs(x1+1)>X) printf("%gi\n\n",x1);
if(fabs(x3)<X&&x1<-X&&fabs(x1+1)<X) printf("-i\n\n");

if(fabs(x3)>X&&x1<-X&&fabs(x1+1)>X) printf("%g-%gi\n\n",x3,fabs(x1));
if(fabs(x3)>X&&x1<-X&&fabs(x1+1)<X) printf("%g-i\n\n",x3,fabs(x1));
if(fabs(x3)>X&&x1>X&&fabs(x1-1)<X) printf("%g+i\n\n",x3,x1);
if(fabs(x3)>X&&x1>X&&fabs(x1-1)>X) printf("%g+%gi\n\n",x3,x1);
}
}
i++;
}
}

...全文
244 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2015-11-24
  • 打赏
  • 举报
回复
_control87, _controlfp Get and set the floating-point control word. unsigned int _control87( unsigned int new, unsigned int mask ); unsigned int _controlfp( unsigned int new, unsigned int mask ); Routine Required Header Compatibility _control87 <float.h> Win 95, Win NT _controlfp <float.h> Win 95, Win NT For additional compatibility information, see Compatibility in the Introduction. Libraries LIBC.LIB Single thread static library, retail version LIBCMT.LIB Multithread static library, retail version MSVCRT.LIB Import library for MSVCRT.DLL, retail version Return Value The bits in the value returned indicate the floating-point control state. See FLOAT.H for a complete definition of the bits returned by _control87. Parameters new New control-word bit values mask Mask for new control-word bits to set Remarks The _control87 function gets and sets the floating-point control word. The floating-point control word allows the program to change the precision, rounding, and infinity modes in the floating-point math package. You can also mask or unmask floating-point exceptions using _control87. If the value for mask is equal to 0, _control87 gets the floating-point control word. If mask is nonzero, a new value for the control word is set: For any bit that is on (equal to 1) in mask, the corresponding bit in new is used to update the control word. In other words, fpcntrl = ((fpcntrl & ~mask) | (new & mask)) where fpcntrl is the floating-point control word. Note The run-time libraries mask all floating-point exceptions by default. _controlfp is a platform-independent, portable version of _control87. It is nearly identical to the _control87 function on Intel (x86) platforms and is also supported by the MIPS and ALPHA platforms. To ensure that your floating-point code is portable to MIPS or ALPHA, use _controlfp. If you are targeting x86 platforms, use either _control87 or _controlfp. The difference between _control87 and _controlfp is the way these two functions treat DENORMAL values. For Intel (x86) platforms, _control87 can set and clear the DENORMAL OPERAND exception mask. ALPHA platforms do not support this exception, and _controlfp does not modify the DENORMAL OPERAND exception mask. The following example demonstrates the difference: _control87( _EM_INVALID, _MCW_EM ); // DENORMAL is unmasked by this call _controlfp( _EM_INVALID, _MCW_EM ); // DENORMAL exception mask remains unchanged The possible values for the mask constant (mask) and new control values (new) are shown in Table R.1. Use the portable constants listed below (_MCW_EM, _EM_INVALID, and so forth) as arguments to these functions, rather than supplying the hexadecimal values explicitly. ALPHA platforms support the DENORMAL input and output values in software. The default behavior of Windows NT on these platforms is to flush the DENORMAL input and output values to zero. _controlfp provides a new mask to preserve and flush the input and output DENORMAL values. Intel (x86) platforms support the DENORMAL input and output values in hardware. The behavior is to preserve DENORMAL values. _control87 does not provide a mask to change this behavior. The following example demonstrates this difference: controlfp( _DN_SAVE, _MCW_DN); // Denormal values preserved by software on ALPHA. NOP on x86 controlfp( _DN_FLUSH, _MCW_DN); // Denormal values flushed to zero by hardware on Alpha. Ignored on x86 Table R.1 Hexadecimal Values Mask Hex Value Constant Hex Value _MCW_DN (Denormal control) 0x03000000 _DN_SAVE _DN_FLUSH 0x00000000 0x01000000 _MCW_EM (Interrupt exception) 0x0008001F _EM_INVALID _EM_DENORMAL _EM_ZERODIVIDE _EM_OVERFLOW _EM_UNDERFLOW _EM_INEXACT 0x00000010 0x00080000 0x00000008 0x00000004 0x00000002 0x00000001 _MCW_IC (Infinity control) 0x00040000 _IC_AFFINE _IC_PROJECTIVE 0x00040000 0x00000000 _MCW_RC (Rounding control) 0x00000300 _RC_CHOP _RC_UP _RC_DOWN _RC_NEAR 0x00000300 0x00000200 0x00000100 0x00000000 _MCW_PC (Precision control) 0x00030000 _PC_24 (24 bits) _PC_53 (53 bits) _PC_64 (64 bits) 0x00020000 0x00010000 0x00000000 Example /* CNTRL87.C: This program uses _control87 to output the control * word, set the precision to 24 bits, and reset the status to * the default. */ #include <stdio.h> #include <float.h> void main( void ) { double a = 0.1; /* Show original control word and do calculation. */ printf( "Original: 0x%.4x\n", _control87( 0, 0 ) ); printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a ); /* Set precision to 24 bits and recalculate. */ printf( "24-bit: 0x%.4x\n", _control87( _PC_24, MCW_PC ) ); printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a ); /* Restore to default and recalculate. */ printf( "Default: 0x%.4x\n", _control87( _CW_DEFAULT, 0xfffff ) ); printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a ); } Output Original: 0x9001f 0.1 * 0.1 = 1.000000000000000e-002 24-bit: 0xa001f 0.1 * 0.1 = 9.999999776482582e-003 Default: 0x001f 0.1 * 0.1 = 1.000000000000000e-002 Floating-Point Support Routines See Also _clear87, _status87
赵4老师 2015-11-24
  • 打赏
  • 举报
回复
如果有人特意构造出一个double不能表示的超小或超大或超精度的根,你用double是无论如何也无法算出它的。 参考include\float.h:
...
#define DBL_DIG         15                      /* # of decimal digits of precision */
#define DBL_EPSILON     2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
#define DBL_MANT_DIG    53                      /* # of bits in mantissa */
#define DBL_MAX         1.7976931348623158e+308 /* max value */
#define DBL_MAX_10_EXP  308                     /* max decimal exponent */
#define DBL_MAX_EXP     1024                    /* max binary exponent */
#define DBL_MIN         2.2250738585072014e-308 /* min positive value */
#define DBL_MIN_10_EXP  (-307)                  /* min decimal exponent */
#define DBL_MIN_EXP     (-1021)                 /* min binary exponent */
#define _DBL_RADIX      2                       /* exponent radix */
#define _DBL_ROUNDS     1                       /* addition rounding: near */
...
lm_whales 2015-11-24
  • 打赏
  • 举报
回复
+,-0 新版本的编译器支持+0,-0; 老版本的编译器往往统一为0, 或者是可以设置的,或可以控制的。 +0,-0 在参与计算时候,通常并无区别,只是计算结果为+0,-0是有区别的。
A1726542850 2015-11-24
  • 打赏
  • 举报
回复
大神能讲的简单点么。。。小白看不懂啊

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧