web-dev-qa-db-ja.com

与えられた数の後の素数を見つける

特定の数より大きい最小素数を見つけるにはどうすればよいですか?たとえば、4の場合、5が必要です。 7を考えると、11が必要です。

これを行うための最良のアルゴリズムに関するいくつかのアイデアを知りたいです。私が考えた方法の1つは、エラトステネスのふるいを通して素数を生成し、指定された数の後の素数を見つけることでした。

35
avd

いくつかの他の方法が提案されており、それらは良いと思いますが、それは本当にその場でどれだけ保存したり計算したいかに依存します。たとえば、非常に大きな数の後の次の素数を探している場合、格納する必要のあるビット数のために、エラトステネスのふるいを使用するのはそれほど素晴らしいことではありません。

または、正しい数が見つかるまで、入力数よりも大きい奇数Nごとに3からsqrt(N)までのすべての奇数整数をチェックできます。もちろん、複合であることがわかったらチェックを停止できます。

別の方法が必要な場合は、素数が見つかるまで、入力数より上のすべての奇数で(入力が1より大きいと仮定して) Miller-Rabin primality test を使用することをお勧めします。ページの下部にあるaのリストに従って特定の範囲を確認すると、確認する必要があるasの数を大幅に削減できます。もちろん、Miller-Rabinで確認する前に、少なくともいくつかの小さい素数(たとえば、3,5,7,11)を確認することをお勧めします。

7
Justin Peel

ソースWikipedia

バートランドの仮定 (実際の定理)は、n> 3が整数の場合、常に少なくとも1つの素数pが存在し、n <p <2n − 2であることを示しています。 :n> 1ごとに、n <p <2nであるような少なくとも1つの素数pが常に存在します。

したがって、範囲(n、2 * n)[nおよび2 * nを除く間隔]でチェックできるよりも、たとえばnという数値が与えられた場合

int GetNextPrime(int n)
{
    bool isPrime = false;
    for (int i = n; i < 2 * n; ++i)
    {
    // go with your regular prime checking routine
    // as soon as you find a prime, break this for loop
    }
}
24
Rajendra Uppal

以前にこれをやったことがあります。

唯一の追加は、 Rajendra's Answer からのバートランドの定理です。

topcoder からの既製コード。

#include<iostream>
using namespace std;

/* This function calculates (ab)%c */
int modulo(int a,int b,int c){
    long long x=1,y=a; // long long is taken to avoid overflow of intermediate results
    while(b > 0){
        if(b%2 == 1){
            x=(x*y)%c;
        }
        y = (y*y)%c; // squaring the base
        b /= 2;
    }
    return x%c;
}

/* this function calculates (a*b)%c taking into account that a*b might overflow */
long long mulmod(long long a,long long b,long long c){
    long long x = 0,y=a%c;
    while(b > 0){
        if(b%2 == 1){
            x = (x+y)%c;
        }
        y = (y*2)%c;
        b /= 2;
    }
    return x%c;
}

/* Miller-Rabin primality test, iteration signifies the accuracy of the test */
bool Miller(long long p,int iteration){
    if(p<2){
        return false;
    }
    if(p!=2 && p%2==0){
        return false;
    }
    long long s=p-1;
    while(s%2==0){
        s/=2;
    }
    for(int i=0;i<iteration;i++){
        long long a=Rand()%(p-1)+1,temp=s;
        long long mod=modulo(a,temp,p);
        while(temp!=p-1 && mod!=1 && mod!=p-1){
            mod=mulmod(mod,mod,p);
            temp *= 2;
        }
        if(mod!=p-1 && temp%2==0){
            return false;
        }
    }
    return true;
}

int main(int argc, char* argv[])
{

    int input = 1000;
    int i = 0;

    if(input%2==0)
        i = input+1;
    else i = input;

    for(;i<2*input;i+=2) // from Rajendra's answer
        if(Miller(i,20)) // 18-20 iterations are enough for most of the applications.
            break;
    cout<<i<<endl;

    return 0;
}
7
Pratik Deoghare

私は通常、それを行う2つの方法を考えています。

  • nからカウントアップし、すべての数が素数かどうかをチェックします
  • 素数を生成し、それらに対してチェックします。 (たぶんそれを事前に行い、既存の素数テーブルを使用するので、毎回計算する必要はありません(Nが事前に計算されたテーブルの範囲内にある限り)

多分これも役立ちます(単に2をあなたの与えられた数に置き換え、Nを無限に置き換えます:D) 2とNの間のすべての素数を見つける

2
samsam

大きなルックアップテーブルを作成してから、指定された番号を検索し、シーケンスの次の値で応答します。

指定された数値の範囲に既知の(適切な)上限がある場合に有効です。

1
Martin
private static int nextPrime(int num) {
        num++;
        for (int i = 2; i <num; i++) {
            if(num%i == 0) {
                num++;
                i=2;
            } else{
                continue;
            }
        }
        return num;
    }
0
ranafeb14