Sottrarre numeri lunghi in JavaScript
-
20-09-2019 - |
Domanda
Perché è q == 0 nella seguente script?
<script>
var start = 1234567890123456789;
var end = 1234567890123456799;
var q = end - start;
alert(q);
</script>
Vorrei che il risultato dovrebbe essere 10. Qual è il modo corretto di sottrarre questi due numeri?
Soluzione
Poiché i numeri in JavaScript sono galleggianti-point. Essi hanno limitato la precisione.
Quando JavaScript vede una lunghissima serie, si arrotonda al numero più vicino si può rappresentare come un float a 64 bit. Nello script, start
e end
ottenere arrotondato allo stesso valore.
alert(1234567890123456789); // says: 1234567890123456800
alert(1234567890123456799); // says: 1234567890123456800
Non c'è modo integrato a fare l'aritmetica preciso su grandi numeri interi, ma è possibile utilizzare una libreria BigInteger come questo .
Altri suggerimenti
Jason già pubblicato il perché. Per una soluzione, è possibile ottenere una libreria JavaScript BigInt a http: // www- cs-students.stanford.edu/~tjw/jsbn/
const subtract = (a, b) => [a, b].map(n => [...n].reverse()).reduce((a, b) => a.reduce((r, d, i) => {
let s = d - (b[i] || 0)
if (s < 0) {
s += 10
a[i + 1]--
}
return '' + s + r
}, '').replace(/^0+/, ''))
Meglio usare biblioteca big-intero per queste cose, in modo da gestire tutti i diversi casi di test.
Questa è solo per il un caso generale è possibile utilizzare ....
Si è spiegato nel JavaScript documentazione :
PaginaSecondo lo standard ECMAScript, c'è solo un tipo di numero: doppia precisione 64- bit formato binario IEEE 754 valore (numeri tra
-(2
53
-1)
e2
53
-1
). Non v'è alcun tipo specifico per gli interi.
formato in virgola mobile a doppia precisione spiega:
Tra
2
52
= 4,503,599,627,370,496
e2
53
= 9,007,199,254,740,992
i numeri rappresentabili sono esattamente i numeri interi. Per la gamma successiva, da2
53
per2
54
, tutto è moltiplicato per2
, in modo che i numeri rappresentabili sono quelli pari, ecc.
(Tutti i numeri interi più piccoli di 2
52
sono rappresentati esattamente.)
1234567890123456789
e 1234567890123456799
sono più grandi di 2
60
= 1152921504606846976
. A tale portata solo circa 1% dei numeri interi sono memorizzati esattamente con doppia precisione formato in virgola mobile.
Questi due non possono essere immagazzinate esattamente. Entrambi sono arrotondati a 1234567890123456800
.
Il JavaScript documentazione anche spiegato come dire se un numero un numero intero viene memorizzato esattamente:
[...] e partendo da ECMAScript 6, si è anche in grado di verificare se un numero è in doppia precisione in virgola mobile intervallo di numeri utilizzando
Number.isSafeInteger()
così comeNumber.MAX_SAFE_INTEGER
eNumber.MIN_SAFE_INTEGER
. Al di là di questa gamma, numeri interi in JavaScript non sono più sicuri e sarà un punto di approssimazione doppia precisione floating del valore.