C语言学习1:素数的判定与素数表的生成
摘要:本文主要探究素数的判别和素数表的生成,为初学时写下作为学习笔记。
一、素数的判定
1.平方根以下遍历法
基本思想:
由数学证明可知,若要判定一个数是否为素数,只需将其除以 [ 2 , sqrt(x) ) , 其中x是这个数本身。另外为了优化计算,可以先判定是否为非2整数。基于这个思想,我们可以给出以下代码。
int isPrime ( int x )
{
int ret = 1;
int i;
if ( x==1 || x%2 == 0 && x!=2 )
{
ret = 0;
}
for ( i=3; i<sqrt(x); i+=2 )
{
if ( x % i == 0 )
{
ret = 0;
break;
}
}
return ret;
}
2.素数表法
基本思想:
判定一个数是不是素数,只需判定它是不是之前的所有素数的倍数即可,因此,我们可以使用递归的方法,边扩充素数表边判定是否为素数,此方法适合大批量的判定,也适用于素数表的生成。
在这里插入#include <stdio.h>
int isPrime(int x, int KnownPrimes[], int numberofKnownPrimes );
int main()
{
const int number = 100;
int prime[100] = {2};
int count = 1;
int i = 3;
while ( count < number )
{
if ( isPrime( i, prime, count ) )
{
prime[count++] = i;
}
i++;
}
for ( i=0; i<number; i++ )
{
printf("%d",prime[i]);
if ( (i+1)%5 )
{
printf("\t");
}
else printf("\n");
}
return 0;
}
int isPrime(int x, int KnownPrimes[], int numberofKnownPrimes )
{
int ret = 1;
int i;
for ( i=0; i<numberofKnownPrimes; i++ )
{
if ( x % KnownPrimes[i] == 0 )
{
ret = 0;
break;
}
}
return ret;
}
二、素数表的生成
在上面一.2中我们给出了一种素数表的生成方法,它是基于之前的素数表进行递归的方法,接下来我们将给出另一种方法。
基本思想:
从2开始,将目前操作数的倍数标记为非素数,再将操作数换成下一个“目前为素数的数”,如此直至到达范围终点,留下的数即为素数。
#include <stdio.h>
int main()
{
const int maxNumber = 25;
int isPrime[maxNumber];
int i;
int x;
for ( i=0; i<maxNumber;i++ )
{
isPrime[i] = 1;
}
for ( x=2; x<maxNumber; x++ )
{
if ( isPrime[x] )
{
for ( i=2; i*x<maxNumber; i++ )
{
isPrime[i*x] = 0;
}
}
}
for ( i=2; i<maxNumber; i++ )
{
if ( isPrime[i] )
{
printf("%d\t",i);
}
}
printf("\n");
return 0;
}
三、总结感悟
- 由1.1我们可以看到,数学中的知识对于简化计算机的算法具有很大作用,我们不能单纯的将计算机作为执行大量简单指令的工具,更重要的是实现程序员自身逻辑性和数学优化能力,减轻计算机的负担。
- 由1.2我们可以看到,递归(姑且允许我这么表达)的思想可以用在某些算法中,起到优化的作用,但是由于我们初学者将循环使用的较为死板,往往意识不到这些问题,这就要求我们放开眼界、解放思想并多加练习。
- 最想说的是2.1,这个算法将人类逻辑中的优化和计算机擅长的遍历结合起来,有效的规避了人类思想中不适合大量数的遍历和计算机算法过于“肤浅”带来的计算量过大问题,这算是我学习C语言遇到的第一个自认为较为不错的程序吧,与君共勉,Cheers!
附:学习来源:中国大学Mooc-浙大翁恺老师-C语言程序设计-8.2:数组运算
链接 :https://www.icourse163.org/learn/ZJU-9001#/learn/content?type=detail&id=129003&cid=145002&replay=true