谭浩强C程序设计习题6-1思考(用筛选法求100之内的素数)
第一步先理解题目,题目有两个关键词,一是筛选法,二是素数。先理解这两个词语的意思,①筛选法:筛选法又称筛法,具体做法是:先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛”,简称“筛法”。(引用自百度百科)②素数:素数我们很熟悉了,就是质数,除了1和本身没有别的因数。
由于现阶段还没有学习结构体和指针,无法建立一个有序链表进行元素的删除,所以先把不是素数的元素标识为0,最后输出非0元素即可。代码如下:
#include<stdio.h> /*用筛选法求100之内的素数*/ int main(void) { int num[100]; //定义一个包含100个元素的数组 for(int m = 0; m<100; m++) num[m] = m+1; //将1-100赋值给num num[0] = 0; //1不属于素数,将其标识为0 for(int i = 1; i<100; i++) { if(num[i] == 0) continue; //如果该数被筛选除掉(为0),则跳过 else { for(int j = i+1; j<100; j++) { if(num[j]%num[i] == 0) num[j] = 0; /*num[j]是num[i]的倍数,非质数,标识为0*/ } } } for(int n = 0; n<100; n++) { if(num[n] != 0) printf("%d\n",num[n]); //输出筛选后的数 } return 0; }
代码在VScode上运行可以得出正确的素数。
下面把《C程序设计(第五版)学习辅导》中的参考答案放在下面,并比较一下和自己写的代码的区别。
#include<stdio.h> #include<math.h> //程序中用到求平方根函数sqrt int main() { int i,j,n,a[101]; //定义a数组包含101个元素 for(i = 1; i<=100; i++) //a[0]不用,只用a[1]~a[100] a[i] = i; //使a[1]~a[100]的值为1~100 a[1] = 0; //先“挖掉”a[1] for(i=2; i<sqrt(100);i++) for(j=i+1; j<=100; j++) { if(a[i]!=0 && a[j]!=0) if(a[j]%a[i] == 0) a[j] = 0; //把非素数“挖掉” } printf("\n"); for(i=2,n=0; i<=100; i++) { if(a[i]!=0) //选出值不为0的数组元素,即素数 { printf("%5d",a[i]); //输出素数,宽度为5列 n++; //累积本行已输出的数据个数 } if(n==10) { printf("\n"); n = 0; } } printf("\n"); return 0; }
官方题解有两个主要的优点,第一是第一层循环时只用循环2到sqrt(100),大大缩短了总程序的运算时间。(为什么可以循环到sqrt(100)而不是100或者100/2?)第二是加入了控制输出元素每行个数的循环块,使得输出更加美观和节省屏幕空间。
总的来说个人的解题思路和官方的是一样的,这题个人打80分吧。

浙公网安备 33010602011771号