程序如下: main( ) { int n,i; long int s; printf(" please input n (n>=0) :"); scanf("%d" , &n); if (n>=0) { s = 1 ; if (n>0) { i = 1 ; while (i<=n) { s * = i ; i = i + 1 ; } } printf("%d! = %ld \n",n,s); } else printf("Invalid input! \n"); } 运行结果如下: please input n(n>=0): 0 0!= 1
please input n(n>=0): 6 6!= 720
please input n(n>=0): - 2 Invalid input!
考察图3- 9中循环部分的流程图可以看出,在循环前各变量应有合适的值( s = 1 ),另外,控制循环结束的变量(此处为i )必须在循环体中被改变,否则,循环将无限进行下去,成为死循环。
[例3-12] 利用格里高利公式求p : p/4 = 1 - 1/3 + 1/5 - 1/7 + ... 直到最后一项的绝对值小于等于1 0- 6为止。 程序如下: # include # include { main( ) { double e,p i ; long int n,s ; t = 1.0; n = 1; s = 1; pi = 0.0; while (fabs(t)>=1e-6) { p i = p i + t ; n = n + 2 ; s = -s; t = (float)(s) / (float)(n); } pi = pi * 4; printf(" pi = %lf\n" ,pi); } 运行结果为: pi = 3.141591 本题中,将多项式的每一项用t表示, s代表符号,在每一次循环中,只要改变s、n的值,就可求出每一项t。 一般情况下, w h i l e型循环最适合于这种情况:知道控制循环的条件为某个逻辑表达式的值,而且该表达式的值会在循环中被改变,如同例3 - 1 2的情况一样。
3.4.2 do... while 语句 在C语句中,直到型循环的语句是do . . . while ,它的一般形式为: do 语句while <表达式> 其中语句通常为复合语句,称为循环体。 d o. . .while 语句的流程图见图3 - 1 0
例[3-13] 计算sin(x) = x- x3/3! + x5/5! - x7/7! + ... 直到最后一项的绝对值小于1e - 7时为止。 分析:这道题使用递推方法来做。 让多项式的每一项与一个变量n对应, n的值依次为1,3,5,7,. . .,从多项式的前一项算后一项,只需将前一项乘一个因子: ( - x 2) / ( ( n - 1 ) * n ) 用s表示多项式的值,用t表示每一项的值,程序如下: #include # include main( ) { double s,t,x ; int n ; printf("please input x :"); scanf("%lf" ,&x); t = x; n=1; s = x ; do { n = n + 2 ; t = t * ( - x * x ) / ((float)(n) -1)/(float)(n); s = s + t ; } while (fabs(t)>=1e-7); printf("sin(%f )=%lf" ,x,s ) ; } 运行结果如下: please input x:1.5753 sin( 1.575300) = 0.999999
[例3-17] 计算半径为1到1 5的圆的面积,仅打印出超过5 0的圆面积。 #include main( ) { int r; float area; for (r=1;r<=5;r++) { area = 3.141593 * r * r; if( area < 50.0 ) continue; printf("square =%f",area); } } 结果为: square = 50.265488 square = 78.539825 同break一样, continue语句也仅仅影响该语句本身所处的循环层,而对外层循环没有影
3.4.5 程序应用举例 [例3-18] 验证哥德巴赫猜想:任一充分大的偶数,可以用两个素数之和表示,例如: 4 = 2 + 2 6 = 3 + 3 .... 98 = 19 + 79 哥德巴赫猜想是世界著名的数学难题,至今未能在理论上得到证明,自从计算机出现后,人们就开始用计算机去尝试解各种各样的数学难题,包括费马大定理、四色问题、哥德巴赫猜想等,虽然计算机无法从理论上严密地证明它们,而只能在很有限的范围内对其进行检验,但也不失其意义。费马大定理已于1 9 9 4年得到证明,而哥德巴赫猜想这枚数学王冠上的宝石,至今无人能及。 分析:我们先不考虑怎样判断一个数是否为素数,而从整体上对这个问题进行考虑,可以这样做:读入一个偶数n,将它分成p和q,使n = p + q。怎样分呢?可以令p从2开始,每次加1,而令q = n - p,如果p、q均为素数,则正为所求,否则令p = p + q再试。 其基本算法如下: 1) 读入大于3的偶数n。 2) P=1 3) do { 4) p=p+1;q = n-p ; 5) p是素数吗? 6) q是素数吗? 7) } while p、q有一个不是素数。 8 ) 输出n = p + q。 为了判明p、q是否是素数,我们设置两个标志量flagp和flagq,初始值为0,若p是素数,令flagp = 1,若q是素数,令flagq = 1,于是第7步变成: 7) } while (flagp*flagq==0); 再来分析第5、第6步,怎样判断一个数是不是素数呢? 素数就是除了1和它自身外,不能被任何数整除的整数,由定义可知: 2、3、5、7、11、1 3、1 7、1 9等是素数; 1、4、6、8、9、1 0、1 2、1 4等不是素数; 要判断i是否是素数,最简单的办法是用2、3、4、⋯⋯i-1这些数依次去除i,看能否除尽,若被其中之一除尽,则i不是素数,反之,i是素数。 但其实,没必要用那么多的数去除,实际上,用反证法很容易证明,如果小于等于i的平方根的数都除不尽,则i必是素数。于是,上述算法中的第5步、第6步可以细化为: 第5)步p是素数吗? flagp = 1 ; for (j=2;j<=[sqrt(p)];j++) if p除以j的余数= 0 { flagp=0; break; } 第6 )步q是素数吗? f l a g q = 1 ; for (j=2;j<=[sqrt(q)];j++) if q除以j的余数= 0 { flagq=0; break; }
程序如下: #include #include main( ) { int j,n,p,q,f l a g p ,f l a g q ; printf("please input n :"); scanf(" %d",& n ) ; if (((n%2)!=0)||(n<=4)) printf("input data error!\n"); else { p = 1 ; do { p = p + 1 ; q = n - p ; flagp = 1 ; for( j = 2; j < = (int)(floor(sqrt((double)(p)))); j++) { if ((p%j)==0) { flagp = 0 ; break; } } flagq = 1; for (j=2;j<=(int)(floor(sqrt((double)(q))));j++) { if ((q%j)==0) { flagq = 0; break; } } } while (flagp*flagq==0); printf("%d = %d + %d \n" ,n,p,q ); } }