数据类型实验
实验A1:表达式11111*11111的值是多少?把5个1改为6个1呢?9个1呢?
实验结果:
在改为6个1的时候如果仍然用int会得到乘积为负数的错误结果
yes! 11111*11111= 123454321
yes! 111111*111111= -539247567
yes! 111111111*111111111= 1653732529
必须改用long
1 #include <stdio.h>
2 int main()
3 {
4 int a;
5 long b,c;
6 a=11111;
7 printf ("yes! 11111*11111= %d\n ", a*a );
8 b=111111;
9 printf ("yes! 111111*111111= %ld\n ", b*b );
10 c=111111111;
11 printf ("yes! 111111111*111111111= %ld\n ", c*c );
12 return 0;
13 }
yes! 11111*11111= 123454321
yes! 111111*111111= 12345654321
yes! 111111111*111111111= 12345678987654321
关键点:
1.注意int溢出的时候要用long
2.注意输出时候对应用 %ld
实验A2: 把实验A1中的所有数换成浮点数,结果如何?
1 #include <stdio.h>
2 int main()
3 {
4 #if 0 //采用float型
5 float a,b,c;
6 a=11111;
7 printf ("yes! 11111*11111= %f\n ", a*a );
8 b=111111;
9 printf ("yes! 111111*111111= %f\n ", b*b );
10 c=111111111;
11 printf ("yes! 111111111*111111111= %f\n ", c*c );
12 #endif
13
14 #if 1//采用double型
15 double a,b,c;
16 a=11111;
17 printf ("yes! 11111*11111= %f\n ", a*a );
18 b=111111;
19 printf ("yes! 111111*111111= %f\n ", b*b );
20 c=111111111;
21 printf ("yes! 111111111*111111111= %f\n ", c*c );
22 #endif
23 return 0;
24 }
全部使用float型的结果
yes! 11111*11111= 123454320.000000
yes! 111111*111111= 12345654272.000000
yes! 111111111*111111111= 12345679481405440.000000
全部改为double型的结果
yes! 11111*11111= 123454321.000000
yes! 111111*111111= 12345654321.000000
yes! 111111111*111111111= 12345678987654320.000000
对比可发现但精度型的对于结果超过8位会损失精度,而double型对超过16位的数会损失精度。
关键点:
1.关于精度损失的情况
2.输出的时候float和double型在prinf中都用f
正规的定义是f: 以小数形式输出单/双精度,隐含输出6位小数。若指定的精度为0,小数部分(包括小数点都不会输出)
实验A3:表达式sqrt(-10)的值是多少?尝试用各种方法输出,计算过程中系统会报错嘛?
搜索了一下sqrt函数是什么:
原型:extern float sqrt(float x); 用法:#include <math.h> 功能:计算x的平方根。 说明:x应大于等于零。
实验A4:表达式1.0/0.0,0.0/0.0的值是多少?尝试用各种方式输出。在计算过程中会报错吗?
实验代码
1 /** 2 *Function: use different ways to caculate the value of 1.0/0.0 and 0.0/0.0 3 * What're the results seperately? Will any error given by the complier? 4 */ 5 #include<stdio.h> 6 int main() 7 { 8 printf("directly use numbers to do the divede operation.\n"); 9 printf("1.0/0.0=%f\n",1.0/0.0); 10 printf("0.0/0.0=%f\n",0.0/0.0); 11 12 printf("use a param to store value of the first number\n"); 13 float a=1.0,b=0.0; 14 printf("1.0/0.0=%f\n",a/0.0); 15 printf("0.0/0.0=%f\n",b/0.0); 16 17 printf("use a param to store value of the second number\n"); 18 float c=0.0; 19 printf("1.0/0.0=%f\n",1.0/c); 20 printf("0.0/0.0=%f\n",0.0/c); 21 22 printf("use a param to store value of both numbers\n"); 23 float e=1.0,f=0.0,g=0.0,h=0.0; 24 printf("1.0/0.0=%f\n",e/f); 25 printf("0.0/0.0=%f\n",g/h); 26 }
实验结果
edward@edward:~/Desktop/Algorithm$ ./epA4 directly use numbers to do the divede operation. 1.0/0.0=inf 0.0/0.0=-nan use a param to store value of the first number 1.0/0.0=inf 0.0/0.0=-nan use a param to store value of the second number 1.0/0.0=inf 0.0/0.0=-nan use a param to store value of both numbers 1.0/0.0=inf 0.0/0.0=-nan
备注:
1.实验中的打印语句 只是为了方便自己观察 实际比赛是严格禁止输出的!
2.结果中的inf 是指正无穷(负无穷结果前有负号)
-nan An expression representing a value which is “not a number”.
参考http://www.gnu.org/software/libc/manual/html_node/Infinity-and-NaN.html
提升:
由于机器精度有限,当计算中遇到诸如1/0、log(-1)、sqrt(-1)等情况的时候,机器给出的结果就是INF或者NAN。程序里面那么多东西,出错是很正常的。如果在debug的时候,自己心里大概知道什么地方很可能遇到这些类似的情况,就到相应的地方加入一些判断或者输出的语句,将中间的计算过程打印出来,以便排查可能的错误(我不习惯使用gdb。。。)。可是我们该如何去判断这个中间结果是正常的还是INF还是NAN呢? 上面这个链接里给出了一些介绍,我就不必多说了。 按照上面链接里给出的一些提示,可以自己写一些函数来作判断,但是没有必要。直接使用isnan(),isinf()就可以了。 用法很简单,比如,a是某个double变量,那么isnan(a)的结果是:如果a不是NAN,那么返回值就是0,否则是1;isinf()的用法完全一样。
实验A5:表达式1/0的值是多少?在计算的过程中系统会报错吗?
1 #include<stdio.h> 2 int main() 3 { 4 printf("%d\n",1/0); 5 }
报错:浮点数例外(除零啦)
scanf 输入格式实验
用语句scanf("%d%d",&a,&b)来输入两个数,那么这两个数应该以怎么样的格式输入呢?
这个实验比较简单,我集中写几种情况。
1 #include<stdio.h> 2 int main() 3 { 4 int a,b; 5 scanf("%d%d",&a,&b); 6 printf("%d %d\n",a,b); 7 return 0; 8 }
B1:同行输入12和2,并以空格分割,是否达预期?
edward@edward:~/Desktop/Algorithm$ ./epB 12 2 12 2
B2:不同两行中输入12和2,是否达预期?
edward@edward:~/Desktop/Algorithm$ ./epB 12 2 12 2
B3:在实验B1和B2中,在12和2前面和后面加入大量的空格或水平制表符,甚至插入一些空行。
edward@edward:~/Desktop/Algorithm$ ./epB
12
2 12 2
B4:把2换成字符s,重复实验B1~B3。edward@edward:~/Desktop/Algorithm$ ./epB
12 s
12 0
edward@edward:~/Desktop/Algorithm$ ./epB
12
s
12 0
edward@edward:~/Desktop/Algorithm$ ./epB
12
s
12 0
printf 语句输出实验
和上面的实验不同,除了注意现象之外,还要找到问题的解决方法。
C1:仅用一条printf语句,打印1+2和3+4的值,用两个空行隔开。(太简单,略)
C2:试着把%d中的两个字符(百分号和小写字母d)输出到屏幕。
C3:试着把\n中的各个字符(反斜线和小写字母n)输出到屏幕。
1 #include<stdio.h>
2 int main()
3 {
4 printf("%d %d\n", 1+2,3+4);
5 printf("%%d\n");
6 printf("\\n\n");
7 return 0;
8 }
edward@edward:~/Desktop/Algorithm$ ./epC
3 7
%d
\n
C4:像C2 C3那样也需要“特殊方法”才能输出的东西还有哪些? 哪些是printf函数引起的问题,哪些不是?
转义字符是C语言中表示字符的一种特殊形式。通常使用转义字符表示ASCII码字符集中不可打印的控制字符和特定功能的字符,如用于表示字符常量的单撇号( '),用于表示字符串常量的双撇号( ")和反斜杠( /)等。转义字符用反斜杠/后面跟一个字符或一个八进制或十六进制数表示。
转义字符 意义 ASCII码值(十进制)
/a 响铃(BEL) 007
/b 退格(BS) 008
/f 换页(FF) 012
/n 换行(LF) 010
/r 回车(CR) 013
/t 水平制表(HT) 009
/v 垂直制表(VT) 011
// 反斜杠 092
/? 问号字符 063
/' 单引号字符 039
/" 双引号字符 034
/0 空字符(NULL) 000
/ddd 任意字符 三位八进制
/xhh 任意字符 二位十六进制
%的问题是printf引起的!