Skip to content

Instantly share code, notes, and snippets.

@gushwell
Last active February 12, 2018 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gushwell/6da6be89f849098a8ff517234793babd to your computer and use it in GitHub Desktop.
Save gushwell/6da6be89f849098a8ff517234793babd to your computer and use it in GitHub Desktop.
C#:エラトステネスの篩(ふるい)再び ref: https://qiita.com/gushwell/items/6370e32371e983358519
// 1000個の素数を取得
var primes = Primes().Take(1000);
// 500以下の素数を取得
var primes = Primes().TakeWhile(p => p <= 500);
// 500より大きい最初の素数を取得
var prime = Primes().First(p => p > 500);
var primes = Primes();
var primes = Primes();
// 下限、上限が指定できるbool型配列
class BoundedBoolArray {
private BitArray _array;
private int _lower;
public BoundedBoolArray(int lower, int upper) {
_array = new BitArray(upper - lower + 1);
_lower = lower;
}
public bool this[int index] {
get {
return _array[index - _lower];
}
set {
_array[index - _lower] = value;
}
}
}
static IEnumerable<int> Primes() {
// 2,3は既知の素数とする
var primes = new List<int>() { 2, 3 };
foreach (var p in primes)
yield return p;
// 4以上の整数から素数を列挙する。int.MaxValueを超えたときには対処していない
int ix = 0;
while (true) {
int prime1st = primes[ix];
int prime2nd = primes[++ix];
// ふるい用の配列の下限、上限を求め、配列を確保する。
var lower = prime1st * prime1st;
var upper = prime2nd * prime2nd - 1;
// ふるいは、[4:8], [9:24], [25:48], [49:120]... と変化する。
// []内の数値は、配列の下限と上限
var sieve = new BoundedBoolArray(lower, upper);
// 求まっている素数を使い、ふるいに掛ける
foreach (var prime in primes.Take(ix)) {
var start = (int)Math.Ceiling((double)lower / prime) * prime;
for (int index = start; index <= upper; index += prime)
sieve[index] = true;
}
// ふるいに掛けられて残った値が素数。これを列挙する。
// 併せて、求まった素数は、primesリストに記憶していく。
// この素数が次のステップ以降で、ふるいに掛ける際に利用される。
for (int i = lower; i <= upper; i++) {
if (sieve[i] == false) {
primes.Add(i);
yield return i;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment