3 を超えるすべての素数は、次を使用して生成できることがわかっています。
6 * k + 1
6 * k - 1
ただし、上記の式から生成されるすべての数値は素数ではありません。
For Example:
6 * 6 - 1 = 35 which is clearly divisible by 5.
このような状態を解消するために、ふるい法を用いて、上記の式から発生する数の因数となる数を取り除きました。
事実を使用して:
素因数がない数は、素数であると言われます。
- 上記の式を使用してすべての素数を生成できるためです。
- 上記の数の倍数をすべて削除できれば、素数だけが残ります。
1000 未満の素数を生成します。
ArrayList<Integer> primes = new ArrayList<>();
primes.add(2);//explicitly add
primes.add(3);//2 and 3
int n = 1000;
for (int i = 1; i <= (n / 6) ; i++) {
//get all the numbers which can be generated by the formula
int prod6k = 6 * i;
primes.add(prod6k - 1);
primes.add(prod6k + 1);
}
for (int i = 0; i < primes.size(); i++) {
int k = primes.get(i);
//remove all the factors of the numbers generated by the formula
for(int j = k * k; j <= n; j += k)//changed to k * k from 2 * k, Thanks to DTing
{
int index = primes.indexOf(j);
if(index != -1)
primes.remove(index);
}
}
System.out.println(primes);
ただし、この方法では正しく素数が生成されます。これは、Sieve でチェックするすべての数値をチェックする必要がないため、はるかに高速に実行されます。
私の質問は、エッジケースが欠けているということですか? これははるかに優れていますが、これを使用している人を見たことがありません。私は何か間違ったことをしていますか?
このアプローチをさらに最適化できますか?
boolean[]
an の代わりにaを使用するArrayList
方がはるかに高速です。
int n = 100000000;
boolean[] primes = new boolean[n + 1];
for (int i = 0; i <= n; i++)
primes[i] = false;
primes[2] = primes[3] = true;
for (int i = 1; i <= n / 6; i++) {
int prod6k = 6 * i;
primes[prod6k + 1] = true;
primes[prod6k - 1] = true;
}
for (int i = 0; i <= n; i++) {
if (primes[i]) {
int k = i;
for (int j = k * k; j <= n && j > 0; j += k) {
primes[j] = false;
}
}
}
for (int i = 0; i <= n; i++)
if (primes[i])
System.out.print(i + " ");