2010.4.14
生成质数表
书中范例:
- // Program to generate a table of prime numbers
- #include <stdio.h>
- int main (void)
- {
- int p, d;
- _Bool isPrime;
- for ( p = 2; p <= 50; ++p ) {
- isPrime = 1;
- for ( d = 2; d < p; ++d )
- if ( p % d == 0 )
- isPrime = 0;
- if ( isPrime != 0 )
- printf ( “%i ”, p );
- }
- printf ( “/n” );
- return 0;
- }
书中的范例经编译运行后,没有问题。
不过在自己敲代码的时候就有点纳闷,内循环的for语句中第一个if进行判断后执行isPrime=0,和后一个if判断语句中isPrime!=0并不冲突啊,这种非此即彼的判断为什么要用两个if语句而不是if…else呢?如果说只有当isPrime!=0的时候——也就是isPrime=1的时候才执行printf语句,为什么不直接判断p%d!=0然后直接用printf而要多余的引入一个isPrime布尔变量呢?
基于自己的这种疑问,我把程序按照自己的想法进行了修改,为:
- #include <stdio.h>
- int main (void)
- {
- int p, d;
- for (p=2; p<=50; p++)
- {
- for (d=2; d<p; d++)
- if (p%d!=0)
- printf ("%i ", p);
- }
- printf ("/n");
- return 0;
- }
编译没有问题,不过运行时输出了一堆从3到50的数字,整整一个屏幕……当然是自己想当然的修改出错了。
回过头自己看了一下这个简单程序的算法设计,并对照代码进行思考,终于让我弄明白自己错在什么地方。
这个程序的算法设计没什么难以理解的:用从2到p-1的每一个整数去除p,如果任何一个能够整除的话,那么p就不是质数,如果每一个整数都不能整除的话,那么p就是质数。
我自己想像中的简化,就是忽视了“任何一个能够整除”——即是说在2到p-1的众多数中,有很多其实是不能整除的,但是并不是碰到一个不能整除的情况就断定p是质数。如10不能被3整除,但是很显然10不是一个质数。所以,把printf这个用来输出质数的语句放到内循环的for下面紧跟着if(p%d!=0)是不对的。
isPrime这个布尔变量的声明也不是如我所想的多余。在内循环中,只有if而没有else就是没有必要用else。这个内循环中,只要有一个数能整除即p%d==0,isPrime就会被赋值为0而不会再用什么变动,于是后面的printf语句也就不会被执行。而如果内循环中,p%d==0的情况一次都没有出现,那么isPrime=0这条赋值语句也不会执行,由于之前就定义isPrime=1,所以就跳出内循环执行后面的printf语句将确定是质数的p输出。