首先祝大家新年快乐。
在之前的求素数的时候,我们并没有使用数组。
但是这个程序过于臃肿了,我们这个判断的方法是从2到x-1挨个测试是否可以整除,但是当n很大的时候,就会循环很多遍,这样的话这个程序的效率也会很低。
int isPrime(int x)
{
int ret = 1;
int i;
if (x == 1)
ret = 0;
for(i = 2; i < x; i++)
{
if (x%i == 0)
{
ret = 0;
break;
}
}
return ret;
}
还有一种方法就是在循环前先把所有的偶数排除,注意重点是判断是否为2,然后再从3开始把后面的所有奇数挨个循环一遍,这种方法会好一点,可能会循环(n-3)/2+1遍,当n很大的时候就是n/2遍。
int isPrime(int x)
{
int ret = 1;
int i;
if (x == 1||(x%2==0&&x!=2))
ret = 0;
for(i = 3;i < x; i+=2)
{
if (x%i == 0)
{
ret = 0;
break;
}
}
return ret;
}
还有一种方法就是循环的时候不用走到x-1,而是走到x-1的开根就可以了。
具体的原理就是把x硬拆成两个数字的乘积,然后判断带根号的这一部分能不能被小于它的数字整除。
同时需要注意的是如果要使用sqrt的话,那么在函数的前头是要标记一个函数的名称的:
include<math.h>
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)//注意到这里的时候是要在前面加上#include<math.h>
{
if (x % i == 0)
{
ret = 0;
break;
}
}
return ret;
}
还有一种更好的方法就是,不拿更小的数来判断是否能够整除,而是使用更小的素数来进行整除。
但是这个方法有一个要求是我们需要一个已经存在的素数的表格,来进行原数对小的素数的是否整除的判断。
然后我们的目的就是写出一个有关于素数的函数。
具体的解释以及程序会在注释中写出:
//这个程序是用来输出所有的小于输入的数的素数。
#include<stdio.h>
//这个自定义函数是用来判断当前的这个数是不是素数。
int isPrime(int x, int knowPrimes[], int number0fKnownPrimes)
{
int ret = 1;
int i;
for (i = 0; i < number0fKnownPrimes; i++)
{
if (x % knowPrimes[i] == 0)
{
ret = 0;
break;
}
}
return ret;
}
int main()
{
const int number = 10;//算出前number个素数。
int prime[number] = { 2 };//初始第一个数字是2,后面的数字刚开始自动化为0,在后面的计算中来进行输出。
int count = 1;//count的数组的第一个数字已经有值了,所以初始量为1,
int i = 3;
//为了对应后面的每一个prime里面的变量的输出,所以在这里定义一个表头。
{
int i;
printf("\t\t");//这个制表符根据程序实际的空格来进行判断,不同的编译器有不同的空格方法。
for (i = 0; i < number; i++)
{
printf("%d\t", i);
}
printf("\n");
}
while (count < number)
{
if (isPrime(i, prime, count))
{
//由于前面已经赋值了数组第一个,所以这边从count=1开始。
prime[count++] = i;//如果判断结果是素数的话,就挨个放入这个数组。
//注意这里是先对prime[count]赋值,然后再让count+1.这就是前面所说的副作用。
}
{//这个大括号里面的都是调试语句。
//输出的i是第几个测试的数字,count是计数有几个素数。
printf("i=%d\tcnt=%d\t", i, count);//在定义自己的i的时候,可以把外面的i输出。
int i;//定义一个属于调试语句的变量,里面定义的i和外面的i并不冲突。
for(i=0;i<number;i++)//遍历prime数组并且把数组中的每一个数都输出。
{
printf("%d\t", prime[i]);
}
printf("\n");
}
i++;//测试完上一个数,开始测试下一个数。
}
for (i = 0; i < number; i++)
{
printf("%d", prime[i]);
if ((i + 1) % 5)
printf("\t");
else
printf("\n");
}
return 0;
}
还是可以看出,这样的方法还是有一点麻烦的,我们可以换一种方法,就是输出一个表,把里面不是素数的标记,最后输出的就是素数。
具体分为一下几步:
令x为2,
将2x,3x,4x,直至ax<n的数标记为非素数,
令x 为下一个没有标记为非素数的数,重复2;直到所有的数都已经尝试完毕。
来写一个伪代码来看一下程序的具体的过程:
1.开辟prim[n],初始化其所有元素为1,prime[x]为1表示x为素数。
初始化所有数字为1,就是最后的判断,如果数组中的这个元素是1的话,那么它就是素数。
2.令x=2。
3.如果x是素数,则对于(i=2;x*i<n;i++)令prime[i*x]=0。
4.令x++,如果x<n,重复3,否则结束。
#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;
}
最后的输出素数表的程序就是这样的。