1.1 算术表达式
计算机的“本职”工作是计算,因此下面先从算术运算入手,看看如何用计算机进行复杂的计算。
程序1-1 计算并输出1+2的值
#include<stdio.h>
int main()
{
printf("%d\n", 1+2);
return 0;
}
这是一段简单的程序,用于计算1+2的值,并把结果输出到屏幕。如果不知道如何编译并运行这段程序,可阅读附录A或向指导教师求助。
即使读者不明白上述程序除了“1+2”之外的其他代码,仍然可以进行以下探索:试着把“1+2”改成其他内容,而不要修改那些并不明白的代码——它们看上去工作情况良好。
下面做4个实验。
实验1:修改程序1-1,输出3-4的结果。
实验2:修改程序1-1,输出5×6的结果。
实验3:修改程序1-1,输出8÷4的结果。
实验4:修改程序1-1,输出8÷5的结果。
直接把“1+2”替换成“3-4”即可顺利解决实验1,但读者很快就会发现:无法在键盘上找到乘号和除号。解决方法是:用星号“*”代替乘号,而用正斜线“/”代替除号。这样,4个实验都顺利完成了。
等一下!实验4的输出结果居然是1,而不是正确答案1.6。这是怎么回事?计算机出问题了吗?计算机没有出问题,问题出在程序上:这段程序的实际含义并非和我们所想的一致。
在C语言中,8/5的确切含义是8除以5所得商值的整数部分。同样地,(-8)/5的值是-1。那么,如果非要得到8÷5=1.6的结果怎么办?下面是完整的程序。
程序1-2 计算并输出8/5的值,保留小数点后1位
#include<stdio.h>
int main()
{
printf("%.1f\n", 8.0/5.0);
return 0;
}
注意:百分号后面是一个小数点,然后是数字1,最后是小写字母f,千万不能输入错,包括大小写——在C语言中,大写和小写字母代表的含义是不同的。
再来做3个实验。
实验5:把%.1f中的数字1改成2,结果如何?能猜想出“1”的确切意思吗?如果把小数点和1都删除,%f的含义是什么?
实验6:字符串%.1f不变,把8.0/5.0改成原来的8/5,结果如何?
实验7:字符串%.1f改成原来的%d,8.0/5.0不变,结果如何?
实验5并不难解决,但实验6和实验7的答案就很难简单解释了——真正原因涉及整数和浮点数编码,相信多数初学者对此都不感兴趣。原因并不重要,重要的是规范:根据规范做事情,则一切尽在掌握中。
提示1-1:整数值用%d输出,实数用%f输出。
这里的“整数值”指的是1+2、8/5这样“整数之间的运算”。只要运算符的两边都是整数,则运算结果也会是整数。正因为这样,8/5的值才是1,而不是1.6。
8.0和5.0被看作是“实数”,或者说得更专业一点,叫“浮点数”。浮点数之间的运算结果是浮点数,因此8.0/5.0=1.6也是浮点数。注意,这里的运算符“/”其实是“多面手”,它既可以做整数除法,又可以做浮点数除法(1)。
提示1-2:整数/整数=整数,浮点数/浮点数=浮点数。
这条规则同样适用于加法、减法和乘法,不过没有除法这么容易出错——毕竟整数乘以整数的结果本来就是整数。
算术表达式可以和数学表达式一样复杂,例如:
程序1-3 复杂的表达式计算
#include<stdio.h>
#include<math.h>
int main()
{
printf("%.8f\n", 1+2*sqrt(3)/(5-0.1));
return 0;
}
相信读者不难把它翻译成数学表达式
。尽管如此,读者可能还是有一些疑惑:5-0.1的值是什么?“整数-浮点数”是整数还是浮点数?另外,多出来的#include<math.h>有什么作用?
第1个问题相信读者能够“猜到”结果:整数-浮点数=浮点数。但其实这个说法并不准确。确切的说法是:整数先“变”成浮点数,然后浮点数-浮点数=浮点数。
第2个问题的答案是:因为程序1-3中用到了数学函数sqrt。数学函数sqrt(x)的作用是计算x的算术平方根(若不信,可输出sqrt(9.0)的值试试)。一般来说,只要在程序中用到了数学函数,就需要在程序最开始处包含头文件math.h,并在编译时连接数学库。如果不知道如何编译并运行这段程序,可阅读本章末尾的内容。