昨天上C语言上机课的时候,做完了老师要求的几个题目之后,没什么事情了。突然我想起以前高中的时候构思的一个程序,程序很简单,就是一个解一元二次方程的程序。其实,用编程语言来写一个解一元二次方程是很简单的,我写这个主要是想达到一个能带根号输出的目的。
以前也见过很多数学软件有解一元二次方程的功能,当然,如果有实数解的话没有什么问题,但是倘若判别式开方后是无理数的话,这些软件往往都是输出一长串的无理数。试想一下,这样一串数字能直接抄到作业本上么?高中那时就是想写个能在解为无理数时保留根号输出答案,好方便写在作业本上,编译到手机上去用就方便许多了。
昨天就完成了这样一个程序,关键是从书上看到了一个可以解决以前思维被卡住的问题的语句。以前想,要是想保留根号输出,判断是否是无理数是一个大问题。现在想想,其实判断很简单的。对于方程 ax^2+bx+c=0 来说,我们输入的a,b,c都已经被要求为正整数,这样的话判别式开方后若为有理数必定是正整数,若为无理数必定是存在小数部分的。这样想就把是否无理数的判断转换成了是否小数部分为零的判断,这样一下子就方便了很多了。C语言里面是可以强制转换数据类型的,这时候只需要把原本开方的结果和开方后强制转换为整形的结果相比较,看看是否为零就知道此判别式开方是否为零了。
我在程序中是这样判断的:if ((sqrt(d)-(int)sqrt(d))==0) /*说明可以直接输出*/,其中的d为判别式。之前定义了一个字符型变量“genhao”找一个特殊符号来代替根号,我是用的是14(ASCII)——一个音乐的符号(其实关键是打不出根号本身)。后面输出的时候就根据之前的判断输出无解、一个解、两个解(这其中包括有理数解和无理数解两种方式),至于计算的时候为了方便主函数语句的简短写了几个分函数。
=========================================
整体代码如下:
//可以直接写到作业本上的解一元二次方程器
//新增虚数输出
#include "stdio.h"
#include "conio.h"
#include "math.h"
#include "stdlib.h"
//求判别式
int dieta(int a1,int b1,int c1)
{
int d1;
d1=(b1*b1-4*a1*c1);
return (d1);
}
//计算X1的值
double thexa(double a2,double b2,double c2,double d2)
{
double xa;
xa=((-b2)+d2)/(2*a2);
return xa;
}
//计算X2的值
double thexb(double a3,double b3,double c3,double d3)
{
double xb;
xb=((-b3)-d3)/(2*a3);
return xb;
}
int main(void)
{
int a,b,c,d,q,p,tuichu;
double x1,x2,sqd;
char genhao=11;/*定义一个根号的符号*/
open:system("cls");
tuichu=1;
printf("设一元二次方程为:ax^2+bx+c=0。\n");
puts("请输入方程中的a,b,c(请先化简为整数):");
scanf("%d%d%d",&a,&b,&c);
system("cls");
if ((a==0)&&(b==0))
{
printf("输入错误!\n");
goto end;
}
if (a==0) /*当a=0时表示一次函数*/
{
sqd=-((double)c/(double)b);
printf("此为一次方程,您输入的算式为“%dx+%d=0”。\n",b,c);
if (sqd-(int)sqd==0) /*直接输出答案*/
{
printf("此方程解为:%.0f。\n",sqd);
}
else
{
printf(" %d\n",-c);
printf("此方程解为:X= ---\n");
printf(" %d\n",b);
}
goto end;
}
printf("您输入的算式为“%dx^2+%dx+%d=0”。\n",a,b,c);
d=dieta(a,b,c);
if (d<0)
{
printf("此一元二次方程无实数解,其虚数解为:\n");
printf("(注:答案中的“i”表示虚数单位,-1=i*i)\n");
sqd=sqrt(-d);
//通过整形和双精度求根的比较判断是否为无理数
if ((sqrt(-d)-(int)sqrt(-d))==0) /*说明可以直接输出*/
{
p=(-b);
q=(int)sqrt(-d);
printf(" %d+%di\n",p,q);
printf("第一个解为:X1= --------\n");
printf(" %d\n",a*2);
printf(" %d-%di\n",p,q);
printf("第二个解为:X2= --------\n");
printf(" %d\n",a*2);
}
else
{
printf("(注:答案中的“%c”表示根号)\n",genhao);
printf(" %d+%c(%d)i\n",-b,genhao,-d);
printf("第一个解为:X1= -----------\n");
printf(" %d\n",a*2);
printf(" %d-%c(%d)i\n",-b,genhao,-d);
printf("第二个解为:X2= -----------\n");
printf(" %d\n",a*2);
}
}
else
{
if (d==0)
{
x1=(double)(-b)/(double)(2*a);
printf("此方程只有一个解,解为:%.f。\n",x1);
}
else
{
sqd=sqrt(d);
//通过整形和双精度求根的比较判断是否为无理数
if ((sqd-(int)sqd)==0) /*说明可以直接输出*/
{
x1=thexa((double)a,(double)b,(double)c,sqd);
x2=thexb((double)a,(double)b,(double)c,sqd);
if ((x1-(int)x1==0)&&(x2-(int)x2==0))
{
printf("此方程解为 %.f和 %.f。\n",x1,x2);
}
else if ((x1-(int)x1!=0)&&(x2-(int)x2==0))
{
printf(" %d\n",-b+(int)sqd);
printf("此方程解为 --- 和 %.f。\n",x2);
printf(" %d\n",2*a);
}
else if ((x1-(int)x1==0)&&(x2-(int)x2!=0))
{
printf(" %d\n",-b-(int)sqd);
printf("此方程解为 %.f 和 ---。\n",x1);
printf(" %d\n",2*a);
}
else
{
printf("%14d%7d\n",-b+(int)sqd,-b-(int)sqd);
printf("此方程解为 --- 和 ---。\n",x1);
printf("%14d%7d\n",2*a,2*a);
}
}
else /*说明要带根号输出*/
{
printf("注:答案中的“%c”表示根号\n",genhao);
printf(" %d+%c(%d)\n",-b,genhao,d);
printf("第一个解为:X1= -----------\n");
printf(" %d\n",a*2);
printf(" %d-%c(%d)\n",-b,genhao,d);
printf("第二个解为:X2= -----------\n");
printf(" %d\n",a*2);
}
}
}
end:printf("\n按c重新计算,输入其他任意字符退出\n");
tuichu=getch();
if (tuichu=='c')
{
goto open;
}
return 0;
}
========================================
唉,现在才注意到强制转换的实用性,以前看书自学的时候都一直没有注意这个东西。如果早点想到这个的话,在以前高中的时候就写好,编译到手机上用,那就方便太多了(我承认之前想法有点邪恶)。。。