浅谈素数

何为素数,一般想到的就是不能被比他小的数所能整除的数,再进一步想,不能被比他的一半小的数,再进一步,不能被比他的平方根小的数所能整除,能否再优化呢?答案是肯定的,如果一个数不能被比他小的所有素数整除,这个数就是素数,这是素数真正的定义,只要考虑素数就可以了,和上面的结合起来就是如果这个数不有被比他的平方根小的所有素数整除,这个数就是素数.下面是我曾经写的一个程序,用来求m到n之间的素数个数,n小于1000000,如果要更大,就将N改大点,数组a再定义大点即可,求0到1000000的所有素数个数可在一秒内得到结果.

 

#include<stdio.h>
#include<math.h>
#include<time.h>
#define N 1000
int a[168]={2};
void init(void)                //求出1000以内的所有素数,储存在数组中
{
int i,j,k=1,sure=1;
      for(j=3;j<N;j++)
      {
    for(i=2;i<=sqrt(j);i++)
     if(j%i==0)
              {    
      sure=0;
                  break;
              }
          if(sure)
     a[k++]=j;
     sure=1;
}
/*        for(i=0;i<168;i++)        //输出N以内的素数
        printf("%5d",a[i]);
        */
}
    
int prime(long n)            //判断该数是否为素数
{
int i;
      if(n<2)
    return 0;
      if(n==2)
          return 1;
      for(i=0;i<168;i++)
      {
          if(a[i]>sqrt(n))
     break;
          if(n%a[i]==0)
              return 0;
      }
      return 1;
}

int main(void)
{
      long m,n,i;
      clock_t start,over;            // 定义两个变量用来储存时间
      int sum;
      while(scanf("%ld",&n))
      {
    start=clock();            //记录起始时间
          init();
          sum=1;
          for(i=3;i<=n;i+=2)
     if(prime(i))
      sum++;
    printf("%d/n",sum);
          over=clock();            //记录结束时间
          printf("消耗时间:%lfms/n",(double)(over-start));        //输出程序运行时间
      }
      return 0;
}

以上是为了节约空间.如果你认为空间足够大,那么用以下方法即可高效的得到结果(就是所为的筛法求0到1000000内的素数个数,本机测试只需125MS左右,0到10000000内的要1391MS,如果想求更大的,只要将N改得更大即可,不过也有范围,最大值可能与机器有关)

#include<stdio.h>
#include<time.h>
#define N 10000000
int a[N];
void prime(long n)      //用筛法将不是素数的值置0
{
      long i,j;
      a[1]=0;
      for(i=2;i<n;i++)
        a[i]=1;
      for(i=2;i<n/2;i++)
        if(a[i])
          for(j=i*2;j<n;j=j+i)
            a[j]=0;
}
int main()
{
      int m,n,sum,i;
clock_t start,finish;
      while(scanf("%d",&n))
      {
    start=clock();
    prime(n);  
          sum=1;
          for(i=3;i<=n;i++)
                if(a[i])
                    sum++;
            printf("%d/n",sum);
      finish=clock();
      printf("%lf/n",(double)(finish-start));
        }
        return 0;
}

对于第二种方法,本人还在优化中,内存和效率均可提高

为了让程序消耗内在更少,由于数组中储存的只是1和0,所以只需要一位即可储存,所以我用C++改为bool型,另外不用储存偶数的情况,所以对比INT(32位)内在减少了64倍,而在效率上我也优化了3倍左右,具体程序如下:

#include<iostream>
#include<time.h>
#define N 100000000
bool a[N];
using namespace std;

void prime(unsigned long n)      //用筛法将不是素数的值置0
{
       unsigned long i,j;
       a[0]=1;     //2是唯一的偶素数,另作打算
       for(i=3;i<=n;i+=2)     //将大于2小于或等于n的奇数
     a[i/2]=1;
       for(i=3;i<=n/3;i+=2) //只要考虑小于n/3的就可以了,因为乘以2就是偶数,至少也是乘以3,大于n/3的就不用判断
{
     if(a[i/2])
      for(j=i*3;j<=n;j+=2*i) //j的奇数倍的数全部筛选出去
       a[j/2]=0;
}
}
int main()
{
       unsigned long n,sum,i;
clock_t start,finish;
       while(scanf("%d",&n))
       {
start=clock();
prime(n);  
sum=1;
       for(i=3;i<=n;i+=2)
           if(a[i/2])
      sum++;
cout<<"the number of the prime less than n is "<<sum<<endl;
finish=clock();
cout<<"the promgram expends "<<(double)(finish-start)<<"ms"<<endl;
        }
        return 0;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值