簡體   English   中英

C ++質數間隔

[英]C++ prime numbers interval

我必須編寫腳本以在給定范圍內打印素數。 目前,我正在使用以下腳本:

#include <iostream>
using namespace std;
int main()
{
    int n,p,m;
    cin>>n >> m;
    int * arr;

    arr= new  int[m+1];

    for (int i=0; i<=m; i++)
    {
      arr[i]=0;
    }

    for(int i=2;i<=m;i++){
        if(arr[i]==0)
        {   p=i;
            for (int j=2;p*j<=m;j++)
            {
                arr[p*j]=1;
            }
        }
    }

    for(int i=n;i<=m;i++){
        if(arr[i]==0)cout<<i<<endl;
    }
    delete[] arr;
    return 0;
}

它適用於小輸入(它打印1作為質數,但很容易解決)。 但是,當我輸入數字1999998973和1999999973時,它會與bad_alloc崩潰。

我知道我可能做了很多工作,但我不知道如何解決。 我嘗試了一種不同的算法,但是它確實很慢,我需要它在大約2秒鍾左右的時間內打印數字。 有人有主意嗎?

這似乎適用於我從2到500的數字。它不會隨着1999998973至1999999973的范圍而破裂,並且給出了這些我不知道它們是否正確的結果:

1999999003 1999999013 1999999049 1999999061 1999999081 1999999087 1999999093 1999999097 1999999117 1999999121 1999999151 1999999171 1999999207 1999999219 1999999271 1999999321 1999999373 1999999423 1999999439 1999999499 1999999553 1999999559 1999999571 1999999609 1999999613 1999999621 1999999643 1999999 1999199919999991999 19999991999 19999991999 19999991999

int n,p,m;
cout << "enter two numbers" << endl;
cin >> n >> m;
int size = (m - n) + 1; 

int * arr = new  int[size];

// initialize the array to all zeros
for (int i=0; i < size; i++)
{
  arr[i]=0;
}
// loop once for the entire set of numbers from 2 to max value to 
// multiply with (sqrt of top of range)
int max = sqrt(m);

for(int i = 2; i <= max ;i++)
{
    p = i;
    for (int j=2 ; p*j <= m ; j++)
    {
        if ( (p * j) >= n  )
        {
           arr[(p*j) - n] = 1;
        }
    }
}

for(int i = 0; i < size; i++)
{
    if ( arr[i]==0 )
        cout << (i + n) << endl;
}
delete[] arr;

問題是陣列的空間。

選項1:您可以將數組縮小為范圍的大小。 您可以獲得空間,但是您需要進行額外的計算,因為您必須考慮所有在eratostene篩子范圍內的數字。

選項2:使用位而不是整數共壓縮數據。 您可以使用vector<bool>輕松地做到這一點, vector<bool>正是為此而設計的。

使用選項2,您可以保持代碼不變,只需將arr更改為:

vector<bool> arr(m+1);

您甚至可以使用以下命令保存初始化循環:

vector<bool>arr(m+1, false);

無論您采取哪種選擇,我都建議用添加的版本替換您的eratostene篩的內循環:

for (int i = 2; i <= m; i++){    
    if (arr[i] == 0)
    {
        for (int j = i*2; j <= m; j+=i)  // no p, no multiplication, just add i at each iteration
        {
            arr[j] = 1;
        }
    }
}

時間

節省空間會增加時間。 但是我懷疑,即使您有足夠的內存,您也無法在2秒內得到如此龐大的數字的答案。 如果必須處理2 000 000 000個數字,則要求每個數字最多處理1納秒,即一條CPU指令即可滿足您的期望。

我建議使用輪子分解來更改算法。

如所提供的鏈接的第一段所述,您可以通過除以2,3,5,然后除以等於30的模數直到數字的平方根,來確定數字是否為質

下面列出了一種這樣的實現。 通過以這種方式檢查素數,您將不需要創建最大為m數組。 您唯一需要的數組是wheelOf30[]

#include <math.h>

static const bool wheelOf30[] = {
    false,  true, false, false, false, false, false,  true, false, false,  //  1,  7,
    false,  true, false,  true, false, false, false,  true, false,  true,  // 11, 13, 17, 19,
    false, false, false,  true, false, false, false, false, false,  true   // 23, 29.
};

bool isPrime(int num)
{
    // first, modulo by 2, 3, and 5
    if ((num % 2 == 0) || (num % 3 == 0) || (num % 5 == 0))
        return false;

    int rootNum = sqrt(num);
    // and then, divide by the congruent numbers represented by wheel of 30
    for (int i = 7; i <= rootNum; i += 2)
    {
        // divide the number with the ones congruency to modulo 30 is true
        if (wheelOf30[ i % 30 ])
        {
            if (num % i == 0)
                return false;
        }
    }

    return true;
}

您的主程序如下所示:

#include <iostream>

extern bool isPrime(int num);

int main(int argc, const char * argv[])
{
    int n, m;
    cin >> n >> m;

    for (int i=n; i<=m; ++i)
        if (isPrime(i))
            cout << i << endl;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM