Zieht man lange Zahlen in Javascript
-
20-09-2019 - |
Frage
Warum ist q == 0 im folgende Skript?
<script>
var start = 1234567890123456789;
var end = 1234567890123456799;
var q = end - start;
alert(q);
</script>
Ich würde denken, sollte das Ergebnis 10 sein Was ist der richtige Weg, diese beiden Zahlen zu subtrahieren?
Lösung
Da Zahlen in JavaScript sind Gleitkommazahlen. Sie haben begrenzte Genauigkeit.
Wenn Sie JavaScript eine sehr lange Zahl sieht, rundet es auf die nächste Zahl es als 64-Bit-Float darstellen kann. In Ihrem Skript, start
und end
get gerundet auf den gleichen Wert.
alert(1234567890123456789); // says: 1234567890123456800
alert(1234567890123456799); // says: 1234567890123456800
Es gibt keine integrierte Möglichkeit, präzise Arithmetik auf große ganzen Zahlen zu tun, aber Sie können eine BigInteger Bibliothek wie dieses .
Andere Tipps
Jason veröffentlicht bereits das Warum. // www-: Für eine Lösung, können Sie eine Javascript-Bibliothek BigInt unter http bekommen 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+/, ''))
Bessere Nutzung big-Integer-Bibliothek für diese Dinge, um alle verschiedenen Testfälle zu behandeln.
Dies ist nur für den allgemeinen Fall, dass Sie verwenden können ....
Es wird erklärt, in der JavaScript Dokumentation :
Nach dem ECMAScript-Standard, gibt es nur eine Zahl Typ: doppelte Genauigkeit 64- Bit-binär-Format IEEE 754-Wert (Zahlen zwischen
-(2
53
und-1)
2
53
-1
). Es gibt keinen speziellen Typ für ganze Zahlen.
Wikipedia-Seite über double precision floating point Format erklärt:
Zwischen
2
52
= 4,503,599,627,370,496
und2
53
= 9,007,199,254,740,992
die darstellbaren Zahlen sind genau die Zahlen. Für den nächsten Bereich, von2
53
bis2
54
, alles wird durch2
multipliziert, so dass die darstellbaren Zahlen sind die geraden, etc.
(Alle ganzen Zahlen kleiner als 2
52
sind genau dargestellt.)
1234567890123456789
und 1234567890123456799
sind größer als 2
60
= 1152921504606846976
. Bei dieser Größenordnung nur etwa 1% der ganzen Zahlen gespeichert ist genau doppelte Genauigkeit unter Verwendung von Fließkommaformat.
Diese können zwei nicht genau gespeichert werden. Beide sind gerundet auf 1234567890123456800
.
JavaScript Dokumentation erklärt auch, wie man sagen, wenn ein eine ganze Zahl gespeichert ist, genau:
[...] und beginnend mit ECMAScript 6, Sie sind auch in der Lage zu überprüfen, ob eine Zahl in doppelter Genauigkeit ist Gleitkommazahl Bereich mit
Number.isSafeInteger()
sowieNumber.MAX_SAFE_INTEGER
undNumber.MIN_SAFE_INTEGER
. Außerhalb dieses Bereichs, ganze Zahlen in JavaScript sind nicht mehr sicher und werden eine Doppel-precision floating point Annäherung des Wertes sein.