谭浩强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分吧。

posted @ 2020-05-13 20:24  teamcolt  阅读(512)  评论(0)    收藏  举报