web-dev-qa-db-ja.com

素数を見つけるための最速のアルゴリズムはどれですか?

C++を使用して素数を見つける最速のアルゴリズムはどれですか? Sieveのアルゴリズムを使用しましたが、さらに高速にしたいです!

172
kasperasky

Skin of Atkin の非常に高速な実装は、ダンバーンスタインの primegen です。このふるいは、 エラトステネスのふるい よりも効率的です。彼のページにはいくつかのベンチマーク情報があります。

73
Greg Hewgill

本当に高速でなければならない場合は、素数のリストを含めることができます。
http://www.bigprimes.net/archive/prime/

特定の数が素数であるかどうかを知る必要がある場合、さまざまな wikipediaにリストされている素数テスト があります。特に、数値がnotであるかどうかを判断できるので、それらはおそらく最も速い方法で素数を決定する方法です。

27
Georg Schölly

彼、彼は私が古い質問に答える質問ネクロマンサーであることを知っていますが、効率的な素数テストを実装する方法をネットで探しているこの質問を見つけました。

これまで、最速の素数テストアルゴリズムはStrong Probable Prime(SPRP)であると信じています。私はNvidia CUDAフォーラムから引用しています:

数論におけるより実用的なニッチ問題の1つは、素数の識別に関係しています。 Nが与えられた場合、それが素数であるかどうかをどのように効率的に判断できますか?これは単なる理論的な問題ではなく、おそらく特定の範囲内で主要なハッシュテーブルサイズを動的に検索する必要がある場合に、コードで実際に必要になる可能性があります。 Nが2 ^ 30程度の場合、30000分割テストを実行して、任意の要因を検索しますか?明らかにそうではありません。

この問題に対する一般的な実用的な解決策は、オイラー確率素数テストと呼ばれる単純なテストと、ストロング確率素数(SPRP)と呼ばれるより強力な一般化です。これは、整数Nに対して、確率的にそれを素数であるかどうかで分類できるテストであり、テストを繰り返すと正確さの確率が増加します。テスト自体の遅い部分は、主にA ^(N-1)modulo Nに似た値を計算することです。RSA公開キー暗号化バリアントを実装している人は誰でもこのアルゴリズムを使用しています。これは、巨大な整数(512ビットなど)と通常の32または64ビット整数の両方に役立ちます。

テストは、Nの範囲で常に成功することがわかっている特定のテスト入力パラメーターを事前計算することにより、確率的拒否から決定的な素数性の証明に変更できます。残念ながら、これらの「最もよく知られているテスト」の発見は、効果的に巨大な実際には無限)ドメイン。 1980年に、有用なテストの最初のリストがCarl Pomerance(彼のQuadratic SeiveアルゴリズムでRSA-129をファクタリングすることで有名です)によって作成されました。および検索ドメインの制限。 GreathouseとLivingstoneは、これまでWebで http://math.crg4.com/primes.html にある最新の検索結果をリリースしました。

詳細はこちらをご覧ください: http://primes.utm.edu/prove/prove2_3.html および http://forums.nvidia.com/index.php?showtopic=7048

非常に大きな素数を生成する方法が必要なだけで、すべての素数<整数nを生成する必要がない場合は、ルーカスレーマーテストを使用してメルセンヌ素数を検証できます。メルセンヌ素数の形式は2 ^ p -1です。ルーカス・レーマー検定は、メルセンヌ素数に対して発見された最速のアルゴリズムだと思います。

また、最速のアルゴリズムだけでなく最速のハードウェアも使用する場合は、Nvidia CUDAを使用して実装し、CUDAのカーネルを作成してGPUで実行してください。

十分に大きい素数を発見した場合、EFFは5万ドルから25万ドルの賞品を提供します。 https://www.eff.org/awards/coop

25
Mack

AKS Primality Test と呼ばれる、数値Pが素数か合成数かをチェックする100%数学テストがあります。

概念は単純です:数値Pが与えられ、(x-1)^P - (x^P-1)のすべての係数がPで割り切れる場合、Pは素数で、それ以外の場合は合成数です。

たとえば、P = 3を指定すると、多項式が得られます。

   (x-1)^3 - (x^3 - 1)
 = x^3 + 3x^2 - 3x - 1 - (x^3 - 1)
 = 3x^2 - 3x

そして、係数は両方とも3で割り切れるため、数は素数です。

そして、P = 4(素数ではない)の例:

   (x-1)^4 - (x^4-1)
 = x^4 - 4x^3 + 6x^2 - 4x + 1 - (x^4 - 1)
 = -4x^3 + 6x^2 - 4x

そして、ここで、係数64で割り切れないため、素数ではないことがわかります。

多項式(x-1)^PP+1項になり、組み合わせを使用して見つけることができます。したがって、このテストはO(n)ランタイムで実行されます。したがって、0からiまでのpを単純に反復し、残りをテストできるため、これがどれほど役立つかわかりません。

16
Kousha

特定の数が素数かどうかを判断するのはあなたの問題ですか?次に、素数テストが必要です(簡単)。または、指定された数までのすべての素数が必要ですか?その場合、プライムシーブは良好です(簡単ですが、メモリが必要です)。それとも、数の素因数が必要ですか?これには、因数分解が必要になります(最も効率的な方法が本当に必要な場合、大きな数では困難です)。見ている数字の大きさは? 16ビット? 32ビット?より大きい?

賢明で効率的な方法の1つは、素数のテーブルを事前計算し、ビットレベルエンコーディングを使用してファイルに保持することです。ファイルは1つの長いビットベクトルと見なされますが、ビットnは整数nを表します。 nが素数の場合、そのビットは1に設定され、それ以外の場合はゼロに設定されます。ルックアップは非常に高速で(バイトオフセットとビットマスクを計算します)、メモリにファイルをロードする必要はありません。

5

Rabin-Miller は、標準的な確率的素数検定です。 (それをK回実行し、入力数は完全に合成されているか、おそらくエラー4の確率で素数です-K。 (数百回の繰り返しで、ほぼ確実に真実を伝えています)

非確率的(決定論的) ラビンミラーのバリアント があります。

Great Internet Mersenne Prime Search (GIMPS)は、最大の実証済みの素数の世界記録(274,207,281 -2017年6月1日)、 複数のアルゴリズム を使用しますが、これらは特別な形式の素数です。ただし、上記のGIMPSページには、いくつかの一般的な決定論的素数性テストが含まれています。それらは、どのアルゴリズムが「最速」であるかは、テストする数値のサイズに依存することを示しているようです。数値が64ビットに収まる場合は、おそらく数百万桁の素数で機能することを目的とした方法を使用しないでください。

3
Jason S

アプリケーションによって異なります。いくつかの考慮事項があります。

  • 少数の数が素数であるか、特定の制限までのすべての素数が必要か、または(潜在的に)すべての素数が必要か、情報だけが必要ですか?
  • 対処しなければならない数字はどれくらいですか?

Miller-Rabinとアナログのテストは、特定のサイズ(数百万程度)を超える数については、ふるいよりも高速です。その下では、トライアル部門(数個だけの場合)またはシーブを使用する方が高速です。

2
Svante

最速かどうかを判断させていただきます。

using System;
namespace PrimeNumbers
{

public static class Program
{
    static int primesCount = 0;


    public static void Main()
    {
        DateTime startingTime = DateTime.Now;

        RangePrime(1,1000000);   

        DateTime endingTime = DateTime.Now;

        TimeSpan span = endingTime - startingTime;

        Console.WriteLine("span = {0}", span.TotalSeconds);

    }


    public static void RangePrime(int start, int end)
    {
        for (int i = start; i != end+1; i++)
        {
            bool isPrime = IsPrime(i);
            if(isPrime)
            {
                primesCount++;
                Console.WriteLine("number = {0}", i);
            }
        }
        Console.WriteLine("primes count = {0}",primesCount);
    }



    public static bool IsPrime(int ToCheck)
    {

        if (ToCheck == 2) return true;
        if (ToCheck < 2) return false;


        if (IsOdd(ToCheck))
        {
            for (int i = 3; i <= (ToCheck / 3); i += 2)
            {
                if (ToCheck % i == 0) return false;
            }
            return true;
        }
        else return false; // even numbers(excluding 2) are composite
    }

    public static bool IsOdd(int ToCheck)
    {
        return ((ToCheck % 2 != 0) ? true : false);
    }
}
}

2.40 GHzプロセッサを搭載したCore 2 Duoラップトップで、1〜1,000,000の範囲内の素数を検索して印刷するには、約82秒かかります。そして、それは78,498素数を見つけました。

1
Tayyab Mazhar