C #: Jak zrobić Sieve of Atkin inkrementalnie
Nie wiem, czy to jest możliwe, czy nie, ale muszę tylko zapytać. Moje umiejętności matematyczne i algorytmiczne zawodzą mnie tutaj: P
Chodzi o to, że teraz mam tę klasę, która generuje liczby pierwsze do pewnego limitu:
public class Atkin : IEnumerable<ulong>
{
private readonly List<ulong> primes;
private readonly ulong limit;
public Atkin(ulong limit)
{
this.limit = limit;
primes = new List<ulong>();
}
private void FindPrimes()
{
var isPrime = new bool[limit + 1];
var sqrt = Math.Sqrt(limit);
for (ulong x = 1; x <= sqrt; x++)
for (ulong y = 1; y <= sqrt; y++)
{
var n = 4*x*x + y*y;
if (n <= limit && (n % 12 == 1 || n % 12 == 5))
isPrime[n] ^= true;
n = 3*x*x + y*y;
if (n <= limit && n % 12 == 7)
isPrime[n] ^= true;
n = 3*x*x - y*y;
if (x > y && n <= limit && n % 12 == 11)
isPrime[n] ^= true;
}
for (ulong n = 5; n <= sqrt; n++)
if (isPrime[n])
{
var s = n * n;
for (ulong k = s; k <= limit; k += s)
isPrime[k] = false;
}
primes.Add(2);
primes.Add(3);
for (ulong n = 5; n <= limit; n++)
if (isPrime[n])
primes.Add(n);
}
public IEnumerator<ulong> GetEnumerator()
{
if (!primes.Any())
FindPrimes();
foreach (var p in primes)
yield return p;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Teraz chciałbym pozbyć się limitu, aby sekwencja nigdy się nie zatrzymała (teoretycznie).
Myślę, że może to wyglądać mniej więcej tak:
Zacznij od jakiegoś trywialnego limituZnajdź wszystkie liczby pierwsze do limituWydaj wszystkie nowe liczby pierwszeZwiększ limit (podwajając lub zwiększając stary limit lub coś podobnego)Przejdź do kroku 2I optymalnie, że krok drugi powinien działać tylko między starym limitem a nowym. Innymi słowy, nie powinien ponownie i ponownie znajdować najniższych liczb pierwszych.
Czy można to zrobić w jakiś sposób? Moim głównym problemem jest to, że nie do końca rozumiem cox
iy
na przykład jest w tym algorytmie. Na przykład, czy mógłbym użyć tego samego algorytmu, ale ustawionyx
iy
dooldLimit
(początkowo 1) i uruchom gonewLimit
? A jak by to działało? Jakieś jasne umysły z odrobiną światła na to?
Chodzi o to, że nie będę musiał ustalać tego limitu. Żeby na przykład użyć Linq i po prostuTake()
jednak potrzebuję wielu liczb pierwszych, nie martwiąc się, czy limit jest wystarczająco wysoki, itd.