questa domanda è un po 'avaro sul lato basso nella definizione di ciò che è e accetta un "gran numero" che inizia a solo circa un milione, per cui il current answer funziona; tuttavia, utilizza un bel po 'di memoria come in un numero di 8 byte (un doppio reale di 64 bit) per ogni elemento da setacciare e un altro numero di 8 byte per ogni primo trovato. Questa risposta non funzionerebbe per "grandi numeri", ad esempio circa 250 milioni e oltre, in quanto supererebbe la quantità di memoria disponibile per la macchina di esecuzione JavaScript.
Il seguente codice JavaScript che implementa il Sieve a segmenti segmentato "infinito" (non limitato) di Eratostene supera questo problema in quanto utilizza solo un buffer di setacciamento di pagina 16 Kilobyte un bit ricco (un bit rappresenta un potenziale numero primo) e solo utilizza lo spazio di archiviazione per i numeri primi base fino alla radice quadrata del numero più alto corrente nel segmento di pagina corrente, con i numeri primi effettivamente trovati enumerati nell'ordine senza richiedere alcuna memorizzazione; anche risparmio di tempo da solo setacciando compositi dispari come l'unico primo pari è 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;
})();
Il codice di cui sopra può essere utilizzato per contare i numeri primi fino al limite dato dalla seguente codice 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.';
};
Se i suddetti due pezzi di codice JavaScript sono inseriti in un file denominato app.js nella stessa cartella del seguente codice HTML chiamato qualunque.html, si sarà in grado di eseguire il codice nel browser aprendo il file HTML in esso:
<!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>
Questo codice può setaccio a un miliardo di gamma è un paio di 10 di secondi quando viene eseguito su un motore di esecuzione JavaScript utilizzando la compilazione Just-In-Time (JIT) come il motore V8 di Google Chrome. Ulteriori guadagni possono essere ottenuti utilizzando la fattorizzazione di ruote estreme e il pre-culling dei buffer di pagina dei numeri primi più bassi, nel qual caso la quantità di lavoro eseguita può essere ridotta di un ulteriore fattore di quattro, il che significa che il numero di numeri primi può essere contato fino a un miliardo in pochi secondi (il conteggio non richiede l'enumerazione come qui usata, ma piuttosto può utilizzare il conteggio dei bit per cercare le tabelle sui buffer del segmento di pagina direttamente), sebbene a costo di una maggiore complessità del codice.
state facendo il vostro setaccio volutamente lento, facendo uso di 'Array # indexOf' e' Array # splice' – Alexander
tua funzione restituisce [[2], 3] al posto di [2,3] su input di 5 ... – loxxy