to pytanie jest trochę skąpy zaniżone w definicji tego, co jest „duża liczba” i akceptuje że zaczyna się od zaledwie około miliona, dla którego działa current answer; jednak używa dość dużej ilości pamięci, jak w przypadku jednej 8-bajtowej liczby (podwójna liczba rzeczywista z 64 bitów) dla każdego przesiewanego elementu i kolejnej 8-bajtowej liczby dla każdego znalezionego prime. Ta odpowiedź nie zadziałałaby dla "dużych liczb", powiedzmy około 250 milionów i więcej, ponieważ przekraczałaby ilość pamięci dostępnej dla maszyny wykonawczej JavaScript.
Następujący kod JavaScript implementujący "nieskończoną" (nieograniczoną) stronę Segmentowaną sito Eratostenesa rozwiązuje ten problem, ponieważ wykorzystuje tylko jeden bitowy pakiet przesiewania podzielony na segmenty o wielkości 16 kilobajtów (jeden bit reprezentuje jeden potencjalny numer główny) i tylko wykorzystuje pamięć podstawową dla liczb pierwszych do pierwiastka kwadratowego z bieżącego najwyższego numeru w bieżącym segmencie strony, z rzeczywistymi znalezionymi liczbami pierwszymi wymienionymi w kolejności bez konieczności przechowywania; również oszczędność czasu tylko przez przesiewanie nieparzyste kompozytów jako jedyny nawet Prime 2:
var SoEPgClass = (function() {
function SoEPgClass() {
this.bi = -1; // constructor resets the enumeration to start...
}
SoEPgClass.prototype.next = function() {
if (this.bi < 1) {
if (this.bi < 0) {
this.bi++;
this.lowi = 0; // other initialization done here...
this.bpa = [];
return 2;
} else { // bi must be zero:
var nxt = 3 + 2 * this.lowi + 262144; //just beyond the current page
this.buf = [];
for (var i = 0; i < 2048; i++) this.buf.push(0); // faster initialization 16 KByte's:
if (this.lowi <= 0) { // special culling for first page as no base primes yet:
for (var i = 0, p = 3, sqr = 9; sqr < nxt; i++, p += 2, sqr = p * p)
if ((this.buf[i >> 5] & (1 << (i & 31))) === 0)
for (var j = (sqr - 3) >> 1; j < 131072; j += p)
this.buf[j >> 5] |= 1 << (j & 31);
} else { // other than the first "zeroth" page:
if (!this.bpa.length) { // if this is the first page after the zero one:
this.bps = new SoEPgClass(); // initialize separate base primes stream:
this.bps.next(); // advance past the only even prime of 2
this.bpa.push(this.bps.next()); // keep the next prime (3 in this case)
}
// get enough base primes for the page range...
for (var p = this.bpa[this.bpa.length - 1], sqr = p * p; sqr < nxt;
p = this.bps.next(), this.bpa.push(p), sqr = p * p);
for (var i = 0; i < this.bpa.length; i++) { //for each base prime in the array
var p = this.bpa[i];
var s = (p * p - 3) >> 1; //compute the start index of the prime squared
if (s >= this.lowi) // adjust start index based on page lower limit...
s -= this.lowi;
else { //for the case where this isn't the first prime squared instance
var r = (this.lowi - s) % p;
s = (r != 0) ? p - r : 0;
}
//inner tight composite culling loop for given prime number across page
for (var j = s; j < 131072; j += p) this.buf[j >> 5] |= 1 << (j & 31);
}
}
}
}
//find next marker still with prime status
while (this.bi < 131072 && this.buf[this.bi >> 5] & (1 << (this.bi & 31))) .bi++;
if (this.bi < 131072) // within buffer: output computed prime
return 3 + ((this.lowi + this.bi++) * 2);
else { // beyond buffer range: advance buffer
this.bi = 0;
this.lowi += 131072;
return this.next(); // and recursively loop just once to make a new page buffer
}
};
return SoEPgClass;
})();
Powyższy kod można wykorzystać do policzenia liczby pierwsze aż do danego limitu za pomocą następującego kodu javascript:
window.onload = function() {
var elpsd = -new Date().getTime();
var top_num = 1000000000;
var cnt = 0;
var gen = new SoEPgClass();
while (gen.next() <= top_num) cnt++;
elpsd += (new Date()).getTime();
document.getElementById('content')
.innerText = 'Found ' + cnt + ' primes up to ' + top_num + ' in ' + elpsd + ' milliseconds.';
};
Jeśli powyższe dwa fragmenty kodu JavaScript zostaną umieszczone w pliku o nazwie app.js w tym samym folderze, co poniższy kod HTML o nazwie cokolwiek.html, będzie w stanie uruchomić kod w przeglądarce otwierając plik HTML w nim:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Page Segmented Sieve of Eratosthenes in JavaScript</title>
<script src="app.js"></script>
</head>
<body>
<h1>Page Segmented Sieve of Eratosthenes in JavaScript.</h1>
<div id="content"></div>
</body>
</html>
Kod ten można przesiać do jednego miliarda zakresie jest kilka 10-tych sekund po uruchomieniu na silniku uruchamianie skryptów JavaScript za pomocą kompilacji Just-In-Time (JIT), takiej jak silnik przeglądarki Google Chrome V8. Dalsze korzyści można uzyskać, stosując skrajne rozłożenie koła i wstępne wybieranie buforów stron o najniższych liczbach podstawowych, w którym to przypadku ilość wykonanej pracy można zmniejszyć o kolejny współczynnik równy cztery, co oznacza, że można zliczyć liczbę liczb pierwszych. do miliarda w ciągu kilku sekund (zliczanie nie wymaga wyliczenia, jak tu zastosowano, ale może wykorzystywać tabele z liczbą bitów bezpośrednio na buforach segmentów strony), chociaż kosztem zwiększenia złożoności kodu.
Robisz Twój sito celowo wolniej poprzez wykorzystanie 'Array # indexOf' i' Array # splice' – Alexander
Twój zwraca [[2], 3] zamiast [2,3] na wejściu 5 ... – loxxy