[解決済み] 素数を生成する最もエレガントな方法【クローズド版
質問
この機能を実装する最もエレガントな方法は何でしょう。
ArrayList generatePrimes(int n)
この関数は最初の
n
の素数を生成します (編集: ここで
n>1
である場合)、だから
generatePrimes(5)
は
ArrayList
と
{2, 3, 5, 7, 11}
. (私はこれをC#でやっていますが、Javaの実装でも構いませんし、他の類似の言語でも構いません(Haskellではありません))。
私はこの関数を書く方法を知っていますが、昨晩それを実行したところ、私が期待していたほど素敵な結果にはなりませんでした。以下は、私が思いついたものです。
ArrayList generatePrimes(int toGenerate)
{
ArrayList primes = new ArrayList();
primes.Add(2);
primes.Add(3);
while (primes.Count < toGenerate)
{
int nextPrime = (int)(primes[primes.Count - 1]) + 2;
while (true)
{
bool isPrime = true;
foreach (int n in primes)
{
if (nextPrime % n == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
break;
}
else
{
nextPrime += 2;
}
}
primes.Add(nextPrime);
}
return primes;
}
明らかに非効率であることは避けたいが、速度についてはあまり気にしていない。どの方法(ナイーブ、ふるい、その他)を使っても構いませんが、かなり短く、どのように動作するか明白であって欲しいと思っています。
編集 : 多くは私の実際の質問に答えなかったが、回答してくれたすべての人に感謝する。繰り返しになりますが、私は素数のリストを生成するコードの素敵なクリーンピースが欲しかったです。私はすでにそれを行う方法の束の異なる方法を知っているが、私はそれができるように明確でないコードを書く傾向がある。このスレッドでは、いくつかの良いオプションが提案されています。
- 私がもともと持っていたもののより良いバージョン (Peter Smit、jmservera、Rekreativc)
- エラトステネスの篩の非常に綺麗な実装 (starblue)
-
Java の
BigInteger
とnextProbablePrime
は非常にシンプルなコードで、特に効率的であるとは思えませんが (dfa) - LINQを使用して、素数のリストを遅延して生成します(Maghis)
- たくさんの素数をテキストファイルに入れ、必要なときに読み込む(darin)
編集2 : 私は を C# で実装しました。 に実装してみました。これらはすべて、最初の n の素数を効果的に見つけることができます (そして、私は まともな方法 を使用して、ふるい分けに提供する上限を見つけることができます)。
どのように解決するのですか?
有益な回答をしてくださった方々に感謝します。以下は、私が実装した、最初の n を求めるいくつかの異なる方法をC#で実装したものです。最初の2つの方法は、ここに投稿されたものとほぼ同じです。(投稿者の名前はタイトルの横にあります。) Atkinのふるいはいつかやろうと思っていますが、現在ここにある方法ほど簡単にはいかないと思われます。もし、これらの方法のどれかを改善する方法を知っている人がいたら、ぜひ教えてほしいです。)
標準的な方法 ( ピーター・スミット , jmservera , レクレアティヴ )
最初の素数は2であり、これを素数のリストに追加する。次の素数は、このリスト上のどの数でも均等に割り切れない次の数である。
public static List<int> GeneratePrimesNaive(int n)
{
List<int> primes = new List<int>();
primes.Add(2);
int nextPrime = 3;
while (primes.Count < n)
{
int sqrt = (int)Math.Sqrt(nextPrime);
bool isPrime = true;
for (int i = 0; (int)primes[i] <= sqrt; i++)
{
if (nextPrime % primes[i] == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
primes.Add(nextPrime);
}
nextPrime += 2;
}
return primes;
}
これは、テストする数の平方根まで割り切れるかどうかだけをテストし、奇数だけをテストすることによって最適化されています。の形の数だけをテストすることによって、さらに最適化することができます。
6k+[1, 5]
または
30k+[1, 7, 11, 13, 17, 19, 23, 29]
または
で
.
エラトステネスの篩 ( スターブルー )
に対するすべての素数を見つけます。 k . のリストを作るには、最初の n の素数のリストを作成するために、まず最初に n の値を近似する必要があります。次のような方法である。 に記述されているように で、これを行います。
public static int ApproximateNthPrime(int nn)
{
double n = (double)nn;
double p;
if (nn >= 7022)
{
p = n * Math.Log(n) + n * (Math.Log(Math.Log(n)) - 0.9385);
}
else if (nn >= 6)
{
p = n * Math.Log(n) + n * Math.Log(Math.Log(n));
}
else if (nn > 0)
{
p = new int[] { 2, 3, 5, 7, 11 }[nn - 1];
}
else
{
p = 0;
}
return (int)p;
}
// Find all primes up to and including the limit
public static BitArray SieveOfEratosthenes(int limit)
{
BitArray bits = new BitArray(limit + 1, true);
bits[0] = false;
bits[1] = false;
for (int i = 0; i * i <= limit; i++)
{
if (bits[i])
{
for (int j = i * i; j <= limit; j += i)
{
bits[j] = false;
}
}
}
return bits;
}
public static List<int> GeneratePrimesSieveOfEratosthenes(int n)
{
int limit = ApproximateNthPrime(n);
BitArray bits = SieveOfEratosthenes(limit);
List<int> primes = new List<int>();
for (int i = 0, found = 0; i < limit && found < n; i++)
{
if (bits[i])
{
primes.Add(i);
found++;
}
}
return primes;
}
スンダラムのふるい
私が発見したのは このふるい を発見したのは最近ですが、これは非常に簡単に実装することができます。私の実装はエラトステネスのふるいほど高速ではありませんが、素朴な方法よりはかなり高速です。
public static BitArray SieveOfSundaram(int limit)
{
limit /= 2;
BitArray bits = new BitArray(limit + 1, true);
for (int i = 1; 3 * i + 1 < limit; i++)
{
for (int j = 1; i + j + 2 * i * j <= limit; j++)
{
bits[i + j + 2 * i * j] = false;
}
}
return bits;
}
public static List<int> GeneratePrimesSieveOfSundaram(int n)
{
int limit = ApproximateNthPrime(n);
BitArray bits = SieveOfSundaram(limit);
List<int> primes = new List<int>();
primes.Add(2);
for (int i = 1, found = 1; 2 * i + 1 <= limit && found < n; i++)
{
if (bits[i])
{
primes.Add(2 * i + 1);
found++;
}
}
return primes;
}
関連
-
[解決済み】C# ASP.NET使用時に「WebClientのリクエスト中に例外が発生しました。
-
[解決済み】Unity 「関連するスクリプトを読み込むことができません」「Win32Exception: システムは指定されたファイルを見つけることができません"
-
[解決済み] C#の正しいバージョン番号を教えてください。
-
[解決済み] 乱数(int)を生成する方法を教えてください。
-
[解決済み] Java の配列を表示する最も簡単な方法は何ですか?
-
[解決済み] C#のオートプロパティに初期値を与える最良の方法は何ですか?
-
[解決済み] 英数字のランダムな文字列を生成する方法
-
[解決済み] 簡単な面接問題が難しくなった:1~100の数字が与えられたとき、ちょうどk個の数字が欠けていることを見つけなさい。
-
[解決済み] フラットテーブルをツリーにパースする最も効率的/エレガントな方法は何ですか?
-
[解決済み] 素数かどうかを判断するのに、なぜ平方根まで確認するのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】C#におけるtypedefの等価性
-
[解決済み】C#はJavaのcharAt()と同等?)
-
[解決済み】プロジェクトビルド時のエラー。エディタでスクリプトにコンパイルエラーがあるため、Playerのビルドにエラーが発生する
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】Socket.Selectがエラー "An operation was attempted on something that is not a socket" を返す。
-
[解決済み】HRESULTからの例外:0x800A03ECエラー
-
[解決済み】ランダムなブーリアンを生成する最速の方法
-
[解決済み】データが存在しないのに読み込もうとする試みが無効である