计算一元二次方程的根

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

#define EPS 1e-6

 

int main(int argc, const char * argv[]) {

    float a,b,c,disc,p,q;

    printf("input the coefficients a,b,c\n");

    scanf("%f,%f,%f",&a,&b,&c);

    if(fabs(a)<=EPS) //fabs()是一个对浮点数求绝对值的函数, a=0时,输出“不是一元二次方程 ”

    {

        printf("It is nout a quadartic equation!\n");

        exit(0);//终止程序执行,强制返回操作系统

    }

    disc=b*b-4*a*c; //计算判别式

    p=-b/(2*a);

    q=sqrt(fabs(disc))/(2*a);

    if(fabs(disc)<=EPS) //判断判别式等于0时,输出两个相等的实根

    {

        printf("x1=x2=%.2f\n",p);

    }

    else

    {

        if(disc>EPS)

        {

            printf("x1=%.2f,x2=%.2f\n",p+q,p-q);

        }

        else

        {

            printf("x1=%.2f+%.2fi,",p,q);

            printf("x2=%.2f-%.2fi\n",p,q);

        }

    }

    

}

运行结果:

这里在刚开始测试时,出现了一个错误,如图所示:

得不到正确的结果。

错误的原因时在输入的时候忽略了C语言是从缓冲区读取数据的,应该用空格依次去输入数据,而错误的方法却用了空格键,c语言读取了空格,导致无法计算。

注意:

(1)fabs()和abs()函数的区别,第一,abs()函数是对整数取绝对值,fabs()函数则对浮点数取绝对值。第二,头文件不同,fabs()的头文件是#include<math.h>,而abs()的头文件是#include <stdblid.h>。

(2为什么没有直接和0比较呢?

 答:由于实数在内存中是以浮点形式存储的, 阶码所占的位数决定实数的表数范围,尾数所占的尾数决定实数的精度,ASCII C并没有明确规定三种浮点类型的阶码和尾数所占的位数,不同的c编译器分配给阶码和尾数的尾数是不同的,无论怎样,浮点数在内存中存储时其尾数所占的位数都是有限的,因此其能表示的实数的精度也是有限的,换句话说就是浮点数并非真正意义上的实数,只是在某种范围内的近似,因此只能用近似的方法将实数和0进行比较。

if(disc==0)

这样的比较是错误的,应判断浮点数disc是否近似为0,即是否位于0附近一个很小的区间里[-EPS,EPS],

 

<think>我们参考引用[1]和[2]中的代码,它们都实现了一元二次方程的求解。综合两个引用的优点,我们可以写出一个更完善的程序: 1. 检查二次项系数是否为0(即a是否为0),若为0则不是一元二次方程。 2. 计算判别式delta = b^2 - 4ac。 3. 据delta的值分三种情况:大于0(两个不等实)、等于0(两个相等实)、小于0(无实,但可以输出复数,但题目要求实,所以这里输出无解或者可以考虑输出复数形式,但通常要求实,所以按无解处理;不过引用中都是输出无解,但实际数学上是有复数的,这里我们按实处理,所以当delta<0时输出无解)。 但是,引用[2]中处理了delta=0的情况,而引用[1]只处理了delta>0的情况,没有考虑delta=0的情况(它只判断了大于0,否则就报错,这显然不完整)。因此,我们需要完善。 另外,引用[2]在delta=0时,将x1赋值给x2,但实际上x1和x2相等,所以可以直接赋值:x1=x2=-b/(2*a)。 同时,我们注意到引用[1]中使用了double类型,而引用[2]中系数使用的是int类型,但是double类型。为了更精确,我们统一使用double类型作为系数和的类型。 此外,引用[2]中有一个小错误:在delta=0的情况中,x1被计算了一次,然后又将x1赋值给x2,但接着又写了一句x1=x2,这实际上是不必要的,而且它先计算了x1,然后x1=x2,这样x1的值就被覆盖了。正确的做法是: x1 = x2 = -b / (2*a); 因此,我们综合写出如下代码: 步骤: 1. 输入三个系数a, b, c(double类型) 2. 判断a是否为0(注意浮点数判断是否为0需要用一个很小的数进行判断,因为浮点数有精度问题) 3. 计算delta = b*b - 4*a*c 4. 判断delta: - 若delta > 0,则两个不等实 - 若delta == 0,则两个相等实 - 若delta < 0,则无实(输出无解) 考虑到浮点数比较的精度问题,我们使用一个很小的数(如1e-7)来比较0。 代码如下: </think>以下是计算一元二次方程的C语言代码实现详解: ```c #include <stdio.h> #include <math.h> // 包含sqrt()平方函数 int main() { double a, b, c; // 系数 double delta; // 判别式 double x1, x2; // 方程 // 输入系数 printf("请输入一元二次方程的系数(a, b, c): "); scanf("%lf %lf %lf", &a, &b, &c); // 验证是否为二次方程 if (fabs(a) < 1e-7) { // 浮点数判零需用容差值 printf("错误:二次项系数a不能为零!\n"); return 1; } delta = b * b - 4 * a * c; // 计算判别式 △=b²-4ac // 判别式分类处理 if (delta > 1e-7) { // 两个不等实 x1 = (-b + sqrt(delta)) / (2 * a); x2 = (-b - sqrt(delta)) / (2 * a); printf("两个不等实:\nx1 = %.2f\nx2 = %.2f\n", x1, x2); } else if (fabs(delta) < 1e-7) { // 两个相等实 x1 = x2 = -b / (2 * a); printf("两个相等实:\nx1 = x2 = %.2f\n", x1); } else { // 判别式小于零(复数) double real = -b / (2 * a); double imag = sqrt(-delta) / (2 * a); printf("两个复数:\nx1 = %.2f + %.2fi\nx2 = %.2f - %.2fi\n", real, imag, real, imag); } return 0; } ``` ### 代码说明: 1. **数学原理** 基于一元二次方程公式:$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$ 通过判别式$\Delta = b^2 - 4ac$判断的类型: - $\Delta > 0$:两个不等实 - $\Delta = 0$:两个相等实 - $\Delta < 0$:两个复数(非实) 2. **关键处理** - 使用`double`类型保证计算精度 - 浮点数判零采用容差值`1e-7`(避免浮点误差) - 复数计算:实部 $\frac{-b}{2a}$,虚部 $\frac{\sqrt{|\Delta|}}{2a}$ - 包含错误检测(a=0的非二次方程情况) 3. **输入示例** `x² - 3x + 2 = 0` 输入:`1 -3 2` **输出**: ``` 两个不等实: x1 = 2.00 x2 = 1.00 ``` ### 注意事项: 1. 输入系数时用空格分隔(如:`2.5 -1.3 0.7`) 2. 复数结果使用标准数学表示法(如:`1.25 + 0.75i`) 3. 程序中`%.2f`控制保留两位小数,可据需要修改精度 > 此实现基于标准数学原理[^1],并参考了C语言数值计算的最佳实践[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值