线性素数筛代++码实现,并且和基本的循环除法速度对比

质数定义:

为在大于1的自然数中,除了1和它本身以外不再有其他因数。

意思就是:质数除了1和他本身除以谁也除不尽Σ(っ °Д °;)っ

知道了定义,就可以求质数

方法一

既然质数是除以谁也除不尽,那就把一个数X,除以所有的比他小的数,结果要是都除不尽,这个数就是质数。

void yi()
{
    //求100以内的所有质数,计算i是否为质数
    for (int i = 2; i < 100; i++)
    {
        int sign = 0;       //当i被某一个数除尽的时候,sign变成1
        int sq = sqrt(i);
        //循环除以所有的比2大的数,比自己小的数
        for (int j = 2; j <= sq; j++)
        {
            //有一个,能被i整除,例如    18%3==0,则18不是质数
            if (i%j == 0) { sign = 1; break; }
        }
        if(sign==0)
            cout << "质数:" << i << endl;
    }
}

比较慢的程序,不改变思想,可以降低速度,就是
循环除以所有的比2大的数,比自己小的数
改为
循环除以所有的比2大的数,比sqrt(x)小的数

可以提前判断这个数是素数,省下好多判断

    for (int j = 2; j <= i; j++)
    {
        //有一个,能被i整除,例如    18%3==0,则18不是质数
        if (i%j == 0)   sign=1;
    }


改为
--
    int sq=sqrt(x);
    for (int j = 2; j <= sq; j++)
    {
        //有一个,能被i整除,例如    18%3==0,则18不是质数
        if (i%j == 0)   sign=1;
    }

直接上线性求素数

思想是:任何一个数乘素数,都不是一个素数,用数组arr依次存素数,
在依次计算出来i是否是质数,之后,用i乘以所有的已经求出来的素数
例如当 i=10时
质数有 2 3 5 7
标记
10*2=20
30
50
70
都是合数
然后在数组check中标记 20 30 50 70都是和数
注意:不要把 ( 合数*求出的每个素数 ) 这样会导致重复标记一个数为合数
只需要
这个算法可以一下子求出大量素数,例如前一万个
但是如果判断某个是否为素数,则就比较麻烦了。
算法:判断i是不是素数

基本的数据
求前十万个素数
数组要开到

int const IMAX = 1300000;
int arr[IMAX + 100]{ 0 };           //依次存放求出来的素数 

bool arr2[IMAX * 10 + 100]{ 0 };        //素数的倍数不是素数,不是素数的标记为1 

就够用了
前十万个素数—> 要计算前一百三十万的数
第一万个素数—>要计算前104729个

//基本的循环除法
int division(int IMAX)
{
    int sign = 0;
    int sq = 0;
    int num = 0;
    for (int x = 2; x <= IMAX; x++)
    {
        sq = sqrt(x);
        sign = 0;
        for (int y = 2; y <= sq; y++)
        {
            //有一个,能被i整除,例如    18%3==0,则18不是质数
            if (x % y == 0) { sign = 1; break; }
        }
        if (sign == 0) { num++; }
    }
    cout << "一共有素数" << num << endl;
    return 0;
}
//线性素数法

int const ARR_MAX = 10000000*10;        //数组开到arr_max最大可以求ARR_MAX之间的所有素数 一亿以内的素数
int arr[ARR_MAX + 100]{ 0 };        //依次存放求出来的素数 
bool arr2[ARR_MAX + 100]{ 0 };      //素数的倍数不是素数,不是素数的标记为1 
int LinearPrimeNumbers(int IMAX)
{
    int tot = 0;                //记录素数的数量 
    //从2开始循环判断每个数是否是素数
    for (int i = 2; i<IMAX; i++)
    {
        //在arr2[]数组中没有被标记的 i 则是素数
        if (arr2[i] == 0)
        {
            //把素数存入arr数组中
            arr[tot] = i;
            //素数总和加1 输出
            tot++;
            //cout << i << endl;
        }
        //
        for (int j = 0; j<tot; j++)
        {
            //要标记的数,超出要计算的最大值,跳出
            if ( arr[j] * i > IMAX ) break;
            //标记为合数
            arr2[arr[j] * i] = 1;
            //要是i可以被一个质数整除,则跳出,不再进行其余的剩下的质数*i进行标记
            //目的是为了防止重复标记
            if ( i % arr[j] == 0) break;
        }
    }
    cout << "线性法素数有" << tot << endl;
    return 0;
}
int main()
{
    int IMAX = 5000000*10;
    clock_t cbegin = clock();
    PrimeNumbers::LinearPrimeNumbers(IMAX);
    clock_t cend = clock();
    cout << "计算"<<IMAX << "以内的素数   线性素数筛用时:" << double(cend - cbegin) / CLOCKS_PER_SEC << endl;

    cbegin = clock();
    PrimeNumbers::division(IMAX);
    cend = clock();
    cout << "计算" << IMAX << "以内的素数   循环除法用时:" << double(cend - cbegin) / CLOCKS_PER_SEC << endl;

    return 0;
}

速度对比差距还是非常大的

线性法素数有3001134
计算50000000以内的素数   线性素数筛用时:0.495
一共有素数3001134
计算50000000以内的素数   循环除法用时:72.618
请按任意键继续. . .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值