上面我们学习了if语句,我们已经可以实现在程序运行时去控制程序运行的方向的功能了。但是似乎只有一个if有点不太够用,毕竟人类的语言中是
如果xxx,那么yyy,否则zzz
也就是说,在if所判断的情况之下,还有另一种与之对应的情况。
例如我们在检查用户的输入数据时,发现合法的输入需要给出提示,非法的输入更要给出提示,只有一个if,实现起来就会比较麻烦。好在c语言还提供了另一个关键字:
else
废话不多说,让我们从一个例子开始。
在本文中,我们将学会制作一个简单的计算二次方程的根的计算器,输入a,b,c就可以得到结果。
当然,不能什么都由我来写,请你根据前面所学习的知识,将最基本的部分的代码自己写出来。
我们需要输入a,b,c三个数的值,还需要两个变量x1,x2去保存根的值,因此我们至少需要定义5个变量。接着,因为abc不一定是整数,x1和x2同样,因此我们这里应该选用浮点型变量,请使用double
这里ps一点:今后我们需要使用浮点型变量时,如果float和double都可以满足要求,那么请尽量选择double,double的确会占用比float大一倍的内存,但是以现在计算机的性能来说,多几字节根本看不出区别。另外网上很多人说double会比float慢得多,这是不负责任的说法!现在的CPU都会集成fpu去处理浮点运算,在很多情况下float都是换成double去运算的!因此double有可能和float一样快,甚至是比float更快
感兴趣的参见:http://stackoverflow.com/questions/417568/float-vs-double-performance
好了,快开始写吧!你需要先定义变量,然后告诉用户去输入他们!
在写完之前请不要偷看答案哦!
写出来应该是下面这个样子(答案不唯一):
#include <stdio.h> #include <stdlib.h> int main() { double a, b, c, x1, x2; //abc为方程的abc,x1和x2用于保存方程的根 //先输入数据 printf("请输入a:"); scanf("%lf", &a); printf("请输入b:"); scanf("%lf", &b); printf("请输入c:"); scanf("%lf", &c); printf("正在计算方程%fx^2 + %fx + %f = 0 的根!\n", a, b, c); return 0; }
运行效果
能够用,不过似乎方程显示的结果看起来特别奇怪,因为printf默认的6位对于我们现在来说似乎有点太高了,我们可以让printf自动判断,于是将第16行改成下面这样:
printf("正在计算方程%gx^2 + %gx + %g = 0 的根!\n", a, b, c);
这样看起来就正常多了,下面我们就来完成计算方程的根的代码。
在初中,我们就学到,一元二次方程的求根公式是
我们将输入的abc带入这个公式就可以解出方程的根了,根据前面所学的,我们知道sqrt的计算平方根的程序,那么就有
x1=(-b+sqrt(b*b-4*a*c))/(2*a); x2=(-b-sqrt(b*b-4*a*c))/(2*a);
有人似乎想知道平方是怎么算的,c语言并没有提供直接求平方的运算符,但是我们让这个数自己乘自己不就好了嘛!
加上显示结果的代码,整个程序应该是这样
#include <stdio.h> #include <stdlib.h> int main() { double a, b, c, x1, x2; //abc为方程的abc,x1和x2用于保存方程的根 //先输入数据 printf("请输入a:"); scanf("%lf", &a); printf("请输入b:"); scanf("%lf", &b); printf("请输入c:"); scanf("%lf", &c); printf("正在计算方程%gx^2 + %gx + %g = 0 的根!\n", a, b, c); //计算方程的解 x1=(-b+sqrt(b*b-4*a*c))/(2*a); x2=(-b-sqrt(b*b-4*a*c))/(2*a); printf("x1=%g\tx2=%g\n", x1, x2); return 0; }
我们来编译一下
咦,似乎这一次和平时有点不同,编译信息内出现了两个警告
借此机会,我们正好来学习一下如何从编译信息中找出我们程序的问题
第一行就是个标题,第二行则告诉你,下面出现的信息都是在main这个函数中发现的
第三行前面告诉我们这个警告在第19行的那一串英文的意思是:警告:隐式函数声明 ‘sqrt’ [….]
第四行也是发生在19行,意思是:警告:不兼容的内建函数隐式声明[默认开启]
警告里面提示我们,这个错误和sqrt函数有关,这个警告是如何发生的呢?让我们想一想sqrt是什么函数?数学函数嘛!
再看看代码,我们似乎忘了干一件事情,那就是#include <math.h>!
我们将它加到程序的开头再编译一次
啊哈,这样就没有警告了!这个警告发生的原因就是因为我们使用了数学函数库内的函数又没有include它,至于为什么会这样显示,我们以后再说。
现在我们来运行它,解一个方程x^2 -2x +1 = 0,这个一元二次方程的解显然是x=1,而且只有这一个解
结果很正确,让我们换一个方程试一下,x^2 + x + 1 = 0,这个方程是无解的
nan?这又是什么鬼!nan其实是Not a Number的缩写,意思是这不是一个数字!
为什么会发生这个情况呢?初中的数学就有,当一元二次方程无解时,Δ会<0,这样一来,根号下就会出现一个负数
负数进行开根号运算是没有意义的(实数范围内),sqrt如果遇到你让他计算一个负数的算数平方根时,就会返回一个nan
这样当然不行,在方程没有解的时候,我们应该提醒用户,而不是扔一堆错误让用户去猜测。况且我们应该检查数据的有效性再进行处理(比如开平方运算),这样会比较安全。(sqrt返回nan显然是因为sqrt在计算之前进行了判断)
要判断Δ是不是小于0,很简单,请自己写出代码!
你很可能会这样写
if((B*b-4*a*c) < 0) { printf("此方程无解!\n"); }
然而这样的话,在显示方程无解后还会继续执行下面的语句,也就是说nan依然会显示出来,你可以运行试一试
为此你可能会说,没关系,我们再加上一次判断,如果有解再显示结果
if(delta < 0) { printf("此方程无解!\n"); } //计算方程的解 if(delta >= 0) { x1=(-b+sqrt(b*b-4*a*c))/(2*a); x2=(-b-sqrt(b*b-4*a*c))/(2*a); printf("x1=%g\tx2=%g\n", x1, x2); }
这样就可以正常执行了
但是重复做这种判断是很浪费时间的事情,这里显然只有两种情况:
- Δ小于0 无解
- Δ大于等于0 有解
也就是说,第二种情况正好是第一种情况相反的方向
这时我们就可以使用else
它的格式类似与这样
if(xxx) { yyy; } else { zzz; }
如果xxx的结果为真,那么就执行if内的yyy,否则就执行else内的zzz
这样我们的程序就成了这样
#include <stdio.h> #include <stdlib.h> #include <math.h> // sqrt(double); int main() { double a, b, c, x1, x2; //abc为方程的abc,x1和x2用于保存方程的根 double delta; //先输入数据 printf("请输入a:"); scanf("%lf", &a); printf("请输入b:"); scanf("%lf", &b); printf("请输入c:"); scanf("%lf", &c); printf("正在计算方程%gx^2 + %gx + %g = 0 的根!\n", a, b, c); //计算Δ的值 delta = b*b-4*a*c; //判断方程是否有解 if(delta < 0) { printf("此方程无解!\n"); } //有解才计算方程的解 if(delta >= 0) { x1=(-b+sqrt(delta))/(2*a); x2=(-b-sqrt(delta<span id="transmark"></span>))/(2*a); printf("x1=%g\tx2=%g\n", x1, x2); } return 0; }
除了第二个if,程序中还新增了一个变量,用于保存delta的值,因为程序中多次用到了delta,如果每一次都算一次的话,不仅写着烦,程序的效率也不高
显然使用else使程序逻辑简单了一些
这个还可以啦,