Was ist der höchste ganzzahlige Wert von JavaScript, zu dem eine Zahl gehen kann, ohne an Genauigkeit zu verlieren?

951

Wird dies durch die Sprache definiert? Gibt es ein definiertes Maximum? Ist es in verschiedenen Browsern unterschiedlich?

TALlama
quelle
5
Sie müssen sich bei Bibliotheken wie github.com/MikeMcl/big.js nicht auf die Grenzen von JS verlassen. Siehe hier die Zuverlässigkeitstests
Dmitri Zaitsev,
2
Was ist der höchste ganzzahlige Wert, den Sie mit big.js verwenden können?
George
@ George Hier ist big.js API: mikemcl.github.io/big.js/#dp
simhumileco
Die Frage macht keinen Sinn. Was bedeutet es, dass eine Zahl zu einem ganzzahligen Wert "geht"? Wenn Sie nur fragen möchten, was die höchste Ganzzahl ist, die Sie in JS darstellen können, ist die höchste (endliche) Zahl selbst eine Ganzzahl.
Veky
@DmitriZaitsev Wir müssen nicht mehr auf externe Bibliotheken angewiesen sein (zumindest bei einigen Browsern). 1n << 10000nist eine wirklich, wirklich große Ganzzahl, ohne an Genauigkeit zu verlieren, ohne Abhängigkeiten zu erfordern (und natürlich nicht einmal nahe an einer Grenze).
Amadan

Antworten:

868

JavaScript hat zwei Nummerntypen: Numberund BigInt.

Der am häufigsten verwendete Nummerntyp Numberist eine 64-Bit-Gleitkomma- IEEE 754- Nummer.

Der größte exakte Integralwert dieses Typs Number.MAX_SAFE_INTEGERist:

  • 2 53 -1 oder
  • +/- 9.007.199.254.740.991 oder
  • neun Billiarden sieben Billionen einhundertneunundneunzig Milliarden zweihundertvierundfünfzig Millionen siebenhundertvierzigtausendneunhunderteinundneunzig

Um dies ins rechte Licht zu rücken: Eine Billiarde Bytes ist ein Petabyte (oder eintausend Terabyte).

"Sicher" bezieht sich in diesem Zusammenhang auf die Fähigkeit, Ganzzahlen genau darzustellen und korrekt zu vergleichen.

Aus der Spezifikation:

Beachten Sie, dass alle positiven und negativen Ganzzahlen, deren Größe nicht größer als 2 53 ist, im NumberTyp darstellbar sind (tatsächlich hat die Ganzzahl 0 zwei Darstellungen, +0 und -0).

Um sicher größere Zahlen als diese zu verwenden, müssen Sie verwenden BigInt, die keine Obergrenze haben.

Beachten Sie, dass die bitweisen Operatoren und Shift-Operatoren mit 32-Bit-Ganzzahlen arbeiten. In diesem Fall beträgt die maximale sichere Ganzzahl 2 31 -1 oder 2.147.483.647.

const log = console.log
var x = 9007199254740992
var y = -x
log(x == x + 1) // true !
log(y == y - 1) // also true !

// Arithmetic operators work, but bitwise/shifts only operate on int32:
log(x / 2)      // 4503599627370496
log(x >> 1)     // 0
log(x | 1)      // 1


Technischer Hinweis zum Thema mit der Nummer 9.007.199.254.740.992: Es gibt eine genaue IEEE-754-Darstellung dieses Werts, und Sie können diesen Wert einer Variablen zuweisen und aus dieser lesen, also für sehr sorgfältig ausgewählte Anwendungen im Bereich von ganzen Zahlen kleiner oder gleich Mit diesem Wert können Sie dies als Maximalwert behandeln.

Im allgemeinen Fall müssen Sie diesen IEEE-754-Wert als ungenau behandeln, da nicht eindeutig ist, ob er den logischen Wert 9.007.199.254.740.992 oder 9.007.199.254.740.993 codiert.

Jimmy
quelle
75
Dies scheint richtig zu sein, aber gibt es einen Ort, an dem dies definiert ist, á la Cs MAX_INT oder Javas Integer.MAX_VALUE?
TALlama
48
4294967295 === Math.pow(2,32) - 1;
CoolAJ86
13
Was ist also die kleinste und größte Ganzzahl, mit der wir die genaue Genauigkeit sicherstellen können?
Pacerier
38
Vielleicht erwähnenswert, dass es in Javascript kein aktuelles (int) gibt. Jede Instanz von Number ist (float) oder NaN.
Rote Beete-Rote Beete
53
9007199254740992 ist nicht wirklich der Maximalwert, das letzte Bit hier wird bereits als Null angenommen, und Sie haben 1 Bit Genauigkeit verloren. Die echte sichere Nummer ist 9007199254740991 (Number.MAX_SAFE_INTEGER)
Willem D'Haeseleer
461

> = ES6:

Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;

<= ES5

Aus der Referenz :

Number.MAX_VALUE;
Number.MIN_VALUE;

Peter Bailey
quelle
23
Ich habe die Frage etwas präziser bearbeitet, um die maximalen Ganzzahlwerte und nicht nur den maximalen Zahlenwert zu erhalten. Entschuldigung für die Verwirrung hier.
TALlama
5
Ist das zurückgegebene Ergebnis in allen Browsern garantiert gleich?
Pacerier
7
Beachten Sie, dass dies Number.MIN_VALUEdie kleinstmögliche positive Zahl ist. Der kleinste Wert (dh weniger als alles andere) ist wahrscheinlich -Number.MAX_VALUE.
Michael Scheper
34
ES6 stellt vor Number.MIN_SAFE_INTEGERundNumber.MAX_SAFE_INTEGER
Superlukas
2
Sollten wir in diesem Fall die Antwort ablehnen, weil sie für die aktualisierte Frage falsch ist, oder sie belassen, weil Peter Baily zum Zeitpunkt der Beantwortung Recht hatte?
Raketen sind schnell
112

Es ist 2 53 == 9 007 199 254 740 992. Dies liegt daran, dass Numbers als Gleitkomma in einer 52-Bit-Mantisse gespeichert sind.

Der Mindestwert beträgt -2 53 .

Dies macht einige lustige Dinge passieren

Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true

Und kann auch gefährlich sein :)

var MAX_INT = Math.pow(2, 53); // 9 007 199 254 740 992
for (var i = MAX_INT; i < MAX_INT + 2; ++i) {
    // infinite loop
}

Weiterführende Literatur: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html

Vjeux
quelle
1
Obwohl man in einem vernünftigen Zeitrahmen niemals das Ende dieser for-Schleife erreichen würde, möchten Sie vielleicht sageni += 1000000000
ninjagecko
2
@ninjagecko, er beginnt bei MAX_INT, also ist das Ende genau dort. Auch die Verwendung von i + = 1000000000 würde es nicht länger zu einer Endlosschleife machen. Versuch es.
Ted Bigham
@ TedBigham: Ah oops, war damit zu schnell fertig. Danke, dass du mich zweimal korrigiert hast.
Ninjagecko
Siehe Jimmys Argument für 9.007.199.254.740.991 anstelle von 9.007.199.254.740.992 hier . Das, kombiniert mit meinem Follow-up, scheint überzeugend.
TJ Crowder
60

In JavaScript gibt es eine Nummer namens Infinity.

Beispiele:

(Infinity>100)
=> true

// Also worth noting
Infinity - 1 == Infinity
=> true

Math.pow(2,1024) === Infinity
=> true

Dies kann für einige Fragen zu diesem Thema ausreichend sein.

BananaNeil
quelle
25
Etwas sagt mir, dass Unendlichkeit keine ganze Zahl ist. :)
devios1
7
Es ist jedoch gut genug, eine minVariable zu initialisieren , wenn Sie nach einem Mindestwert suchen.
Djjeck
9
Beachten Sie, dassInfinity - 1 === Infinity
H. Wolper
2
auch (Unendlichkeit <100) => falsch und Math.pow (2.1024) === Unendlichkeit
Sijav
6
Auch nichts wert, dass es auch negative Unendlichkeit behandelt. Also1 - Infinity === -Infinity
dmccabe
41

Jimmys Antwort repräsentiert das kontinuierliche JavaScript-Ganzzahlspektrum korrekt als -9007199254740992 bis einschließlich 9007199254740992 (sorry 9007199254740993, Sie könnten denken, Sie sind 9007199254740993, aber Sie liegen falsch! Demonstration unten oder in jsfiddle ).

console.log(9007199254740993);

Es gibt jedoch keine Antwort, die dies programmatisch findet / beweist (außer der, auf die CoolAJ86 in seiner Antwort anspielte , die in 28,56 Jahren abgeschlossen sein würde;). Daher gibt es hier eine etwas effizientere Möglichkeit, dies zu tun (um genau zu sein, es ist effizienter von etwa 28,559999999968312 Jahren :), zusammen mit einer Test Geige :

/**
 * Checks if adding/subtracting one to/from a number yields the correct result.
 *
 * @param number The number to test
 * @return true if you can add/subtract 1, false otherwise.
 */
var canAddSubtractOneFromNumber = function(number) {
    var numMinusOne = number - 1;
    var numPlusOne = number + 1;
    
    return ((number - numMinusOne) === 1) && ((number - numPlusOne) === -1);
}

//Find the highest number
var highestNumber = 3; //Start with an integer 1 or higher

//Get a number higher than the valid integer range
while (canAddSubtractOneFromNumber(highestNumber)) {
    highestNumber *= 2;
}

//Find the lowest number you can't add/subtract 1 from
var numToSubtract = highestNumber / 4;
while (numToSubtract >= 1) {
    while (!canAddSubtractOneFromNumber(highestNumber - numToSubtract)) {
        highestNumber = highestNumber - numToSubtract;
    }
    
    numToSubtract /= 2;
}        

//And there was much rejoicing.  Yay.    
console.log('HighestNumber = ' + highestNumber);

Briguy37
quelle
8
@ CoolAJ86: Lol, ich freue mich auf den 15. März 2040. Wenn unsere Zahlen übereinstimmen, sollten wir eine Party
schmeißen
var x = Math.pow (2,53) -3; while (x! = x + 1) x ++; -> 9007199254740991
MickLH
@ MickLH: Ich bekomme 9007199254740992 mit diesem Code . Mit welcher JavaScript-Engine testen Sie?
Briguy37
Sie erhalten 9007199254740992 mit Ihrem eigenen Code. Ich habe nicht den endgültigen Wert von x verwendet, sondern die endgültige Auswertung von x ++ aus paranoiden Gründen. Google Chrome übrigens.
MickLH
@MickLH: Die Auswertung x++gibt Ihnen den Wert von x, bevor das Inkrement aufgetreten ist, was wahrscheinlich die Diskrepanz erklärt. Wenn der Ausdruck den gleichen Wert wie der Endwert von x haben soll, sollten Sie ihn in ändern ++x.
Peterflynn
32

Sicher sein

var MAX_INT = 4294967295;

Argumentation

Ich dachte, ich wäre schlau und würde den Wert x + 1 === xmit einem pragmatischeren Ansatz finden.

Meine Maschine kann nur ungefähr 10 Millionen pro Sekunde zählen ... also werde ich in 28,56 Jahren mit der endgültigen Antwort zurückschicken.

Wenn Sie nicht so lange warten können, bin ich bereit, darauf zu wetten

  • Die meisten Ihrer Loops laufen 28,56 Jahre lang nicht
  • 9007199254740992 === Math.pow(2, 53) + 1 ist Beweis genug
  • Sie sollten bleiben 4294967295die Math.pow(2,32) - 1zu vermeiden erwarteten Probleme mit Bitverschiebung

Finden x + 1 === x:

(function () {
  "use strict";

  var x = 0
    , start = new Date().valueOf()
    ;

  while (x + 1 != x) {
    if (!(x % 10000000)) {
      console.log(x);
    }

    x += 1
  }

  console.log(x, new Date().valueOf() - start);
}());
CoolAJ86
quelle
4
Kannst du es nicht einfach bei 2 ^ 53 - 2 starten, um es zu testen? (Ja, das kannst du, ich habe es gerade versucht, auch mit -3, um sicher zu gehen: var x = Math.pow (2,53) -3; while (x! = x + 1) x ++;) -> 9007199254740991
MickLH
Gute Antwort! Außerdem weiß ich, dass der Wert festgelegt ist, aber warum nicht die binäre Suche für seine Suche verwenden?
Higuaro
1
Was macht das für einen Spaß? Außerdem hat mich @ Briguy37 geschlagen: stackoverflow.com/a/11639621/151312
CoolAJ86
Beachten Sie, dass dieser 'sichere' MAX_INT basierend auf 32 Bit beim Vergleich mit Datumswerten nicht funktioniert. 4294967295 ist so gestern!
Jerry
1
Die Antwort "Um sicher zu gehen: var MAX_INT = 4294967295;" ist nicht humorvoll. Wenn Sie nicht Bitshifting betreiben, machen Sie sich darüber keine Sorgen (es sei denn, Sie benötigen ein Int größer als 4294967295. In diesem Fall sollten Sie es wahrscheinlich als Zeichenfolge speichern und eine Bigint-Bibliothek verwenden).
CoolAJ86
29

Die kurze Antwort lautet: "Es kommt darauf an."

Wenn Sie irgendwo bitweise Operatoren verwenden (oder wenn Sie sich auf die Länge eines Arrays beziehen), sind die Bereiche:

Ohne Vorzeichen: 0…(-1>>>0)

Unterzeichnet: (-(-1>>>1)-1)…(-1>>>1)

(Es kommt also vor, dass die bitweisen Operatoren und die maximale Länge eines Arrays auf 32-Bit-Ganzzahlen beschränkt sind.)

Wenn Sie keine bitweisen Operatoren verwenden oder mit Array-Längen arbeiten:

Unterzeichnet: (-Math.pow(2,53))…(+Math.pow(2,53))

Diese Einschränkungen werden durch die interne Darstellung des Typs "Zahl" auferlegt, die im Allgemeinen der Gleitkomma-Darstellung mit doppelter Genauigkeit nach IEEE 754 entspricht. (Beachten Sie, dass im Gegensatz zu typischen vorzeichenbehafteten Ganzzahlen die Größe der negativen Grenze aufgrund der Eigenschaften der internen Darstellung, die tatsächlich eine negative 0 enthält, dieselbe ist wie die Größe der positiven Grenze !)

Danorton
quelle
Dies ist die Antwort, über die ich stolpern wollte, wie man X in eine 32-Bit-Ganzzahl oder eine vorzeichenlose Ganzzahl konvertiert. Hat Ihre Antwort dafür positiv bewertet.
Charlie Affumigato
29

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
WaiKit Kung
quelle
1
Beachten Sie, dass dies (noch) nicht von allen Browsern unterstützt wird! Heute mögen es iOS (nicht einmal Chrome), Safari und IE nicht.
Cregox
5
Bitte lesen Sie die Antwort sorgfältig durch, wir verwenden nicht die Standardimplementierung von Number.MAX_SAFE_INTEGER in ECMAScript 6, wir definieren sie durch Math.pow (2, 53) -1
WaiKit Kung
Ich dachte, es sei nur ein Hinweis darauf, wie es in ECMA 6 implementiert ist! : PI denke, mein Kommentar ist trotzdem gültig. Alles eine Frage des Kontextes. ;)
Cregox
3
Ist es zuverlässig, MAX_SAFE_INTEGERin allen Browsern rückwärts zu rechnen ? Sollten Sie stattdessen vorwärts gehen? Dh Number.MAX_SAFE_INTEGER = 2 * (Math.pow (2, 52) - 1) + 1;
kjv
Ist Math.pow(2, 53)-1eine sichere Operation? Es ist eine größere als die größte sichere Ganzzahl.
Ioquatix
21

Viele Antworten aus früheren Zeiten haben das Ergebnis zeigen , trueder 9007199254740992 === 9007199254740992 + 1zu verifizieren , dass 9 007 199 254 740 991 die maximale und sichere ganze Zahl ist.

Was ist, wenn wir weiter akkumulieren:

input: 9007199254740992 + 1  output: 9007199254740992  // expected: 9007199254740993
input: 9007199254740992 + 2  output: 9007199254740994  // expected: 9007199254740994
input: 9007199254740992 + 3  output: 9007199254740996  // expected: 9007199254740995
input: 9007199254740992 + 4  output: 9007199254740996  // expected: 9007199254740996

Wir konnten feststellen, dass unter den Zahlen von mehr als 9 007 199 254 740 992 , nur gerade Zahlen sind darstellbar .

Es ist ein Eingang, um zu erklären, wie das 64-Bit-Binärformat mit doppelter Genauigkeit dabei funktioniert. Mal sehen, wie 9 007 199 254 740 992 unter Verwendung dieses Binärformats gehalten (dargestellt) werden.

Verwenden Sie eine kurze Version, um dies anhand von 4 503 599 627 370 496 zu demonstrieren :

  1 . 0000 ---- 0000  *  2^52            =>  1  0000 ---- 0000.  
     |-- 52 bits --|    |exponent part|        |-- 52 bits --|

Auf der linken Seite des Pfeils haben wir den Bitwert 1 und einen benachbarten Radixpunkt. Durch Multiplizieren 2^52bewegen wir den Radixpunkt 52 Schritte nach rechts und er geht bis zum Ende. Jetzt erhalten wir 4503599627370496 in binärer Form.

Jetzt beginnen wir, 1 auf diesen Wert zu akkumulieren, bis alle Bits auf 1 gesetzt sind, was 9 007 199 254 740 991 in Dezimalzahl entspricht.

  1 . 0000 ---- 0000  *  2^52  =>  1  0000 ---- 0000.  
                       (+1)
  1 . 0000 ---- 0001  *  2^52  =>  1  0000 ---- 0001.  
                       (+1)
  1 . 0000 ---- 0010  *  2^52  =>  1  0000 ---- 0010.  
                       (+1)
                        . 
                        .
                        .
  1 . 1111 ---- 1111  *  2^52  =>  1  1111 ---- 1111. 

Da im 64-Bit-Binärformat mit doppelter Genauigkeit ausschließlich 52 Bit für den Bruch zugewiesen werden, steht kein Bit mehr zum Hinzufügen einer weiteren 1 zur Verfügung. Wir können also alle Bits auf 0 und zurücksetzen manipuliere den Exponententeil:

  |--> This bit is implicit and persistent.
  |        
  1 . 1111 ---- 1111  *  2^52      =>  1  1111 ---- 1111. 
     |-- 52 bits --|                     |-- 52 bits --|

                          (+1)
                                     (radix point has no way to go)
  1 . 0000 ---- 0000  *  2^52 * 2  =>  1  0000 ---- 0000. * 2  
     |-- 52 bits --|                     |-- 52 bits --|

  =>  1 . 0000 ---- 0000  *  2^53 
         |-- 52 bits --| 

Jetzt bekommen wir die 9 007 199 254 740 992 , und mit der Nummer größer ist als es, was das Format halten könnte , ist 2 mal die Fraktion , bedeutet dies nun all 1 zusätzlich auf dem Bruchteil entspricht tatsächlich bis 2 hinaus, das ist , warum Doppel -präzises 64-Bit-Binärformat kann keine ungeraden Zahlen enthalten, wenn die Zahl größer als 9 007 199 254 740 992 ist :

                            (consume 2^52 to move radix point to the end)
  1 . 0000 ---- 0001  *  2^53  =>  1  0000 ---- 0001.  *  2
     |-- 52 bits --|                 |-- 52 bits --|

Wenn also die Zahl größer als 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984 wird, kann nur das 4-fache der Fraktion gehalten werden:

input: 18014398509481984 + 1  output: 18014398509481984  // expected: 18014398509481985
input: 18014398509481984 + 2  output: 18014398509481984  // expected: 18014398509481986
input: 18014398509481984 + 3  output: 18014398509481984  // expected: 18014398509481987
input: 18014398509481984 + 4  output: 18014398509481988  // expected: 18014398509481988

Wie wäre es mit einer Zahl zwischen [ 2 251 799 813 685 248 , 4 503 599 627 370 496 )?

 1 . 0000 ---- 0001  *  2^51  =>  1 0000 ---- 000.1
     |-- 52 bits --|                |-- 52 bits  --|

Der Bitwert 1 nach dem Radixpunkt ist genau 2 ^ -1. (= 1/2 , = 0,5) Wenn also die Zahl kleiner als 4 503 599 627 370 496 (2 ^ 52) ist, steht ein Bit zur Verfügung, um das 1/2-fache der Ganzzahl darzustellen :

input: 4503599627370495.5   output: 4503599627370495.5  
input: 4503599627370495.75  output: 4503599627370495.5  

Weniger als 2 251 799 813 685 248 (2 ^ 51)

input: 2251799813685246.75   output: 2251799813685246.8  // expected: 2251799813685246.75 
input: 2251799813685246.25   output: 2251799813685246.2  // expected: 2251799813685246.25 
input: 2251799813685246.5    output: 2251799813685246.5

// If the digits exceed 17, JavaScript round it to print it.
//, but the value is held correctly:

input: 2251799813685246.25.toString(2) 
output: "111111111111111111111111111111111111111111111111110.01"
input: 2251799813685246.75.toString(2) 
output: "111111111111111111111111111111111111111111111111110.11"
input: 2251799813685246.78.toString(2)   
output: "111111111111111111111111111111111111111111111111110.11"

Und was ist der verfügbare Bereich des Exponententeils ? Das Format weist 11 Bits dafür zu. Vollständiges Format aus dem Wiki : (Weitere Details finden Sie dort)

IEEE 754 Double Floating Point Format.svg

Geben Sie hier die Bildbeschreibung ein

Damit der Exponententeil 2 ^ 52 ist, müssen wir genau e = 1075 setzen.

Carr
quelle
13

Andere haben die generische Antwort vielleicht bereits gegeben, aber ich dachte, es wäre eine gute Idee, sie schnell zu bestimmen:

for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);

Das gibt mir 9007199254740992 innerhalb von weniger als einer Millisekunde in Chrome 30.

Es werden Potenzen von 2 getestet, um herauszufinden, welche, wenn '1 hinzugefügt' wird, sich selbst entspricht.

Philippe97
quelle
Es könnte Ihre Anwendung zum Absturz bringen, dachte ich.
Sapphire_Brick
8

Alles, was Sie für bitweise Operationen verwenden möchten, muss zwischen 0x80000000 (-2147483648 oder -2 ^ 31) und 0x7fffffff (2147483647 oder 2 ^ 31 - 1) liegen.

Die Konsole zeigt an, dass 0x80000000 gleich +2147483648 ist, 0x80000000 & 0x80000000 jedoch -2147483648.

Scato
quelle
6

Versuchen:

maxInt = -1 >>> 1

In Firefox 3.6 ist es 2 ^ 31 - 1.

Martin Naatz
quelle
2
@ Danorton: Ich bin nicht sicher, ob Sie verstehen, was Sie tun. ^bedeutet zur Macht erhoben . In der Javascript-Konsole ^ist XOR nicht auf
kumarharsh
2
Öffnen Sie die Chrome / Firefox-Konsole. Typ 5 ^ 2. In binär ist 5 101und 2 ist 010. Nun, wenn Sie Bitwise XOR sie, werden Sie lesen, wenn Sie verwirrt 5(101) ^ 2(010) = 7(111) sind. Was hier diskutiert wird, ist Math.pow()nicht der ^Operator
Kumarharsh
3
Auch hier bin ich überhaupt nicht verwirrt. Ich habe kommentiert und abgelehnt, was geschrieben steht . Wenn Math.pow () gemeint ist, sollte dies geschrieben werden. Bei der Beantwortung einer Frage zu JavaScript ist es unangemessen, die Syntax einer anderen Sprache zu verwenden. Es ist noch unangemessener, eine Syntax zu verwenden, die in JavaScript gültig ist, aber eine Interpretation in JavaScript hat, die eine andere Bedeutung hat als beabsichtigt.
Danorton
10
2 ^ 31 schreibt man zwei auf Englisch in die einunddreißigste Potenz. Es ist nicht in einem Codeblock. Würden Sie sich über jemanden beschweren, der a verwendet? in einer Antwort, weil das ein Zeichen mit einer anderen Bedeutung in Javascript ist?
lmm
3
Auch wenn man 2³¹ und nicht 2 ^ 31 im Klartext schreiben sollte , ist dies üblich, da die meisten Tastaturlayouts diese Zeichen standardmäßig nicht haben. Zumindest hatte ich keine Probleme zu verstehen, was in dieser Antwort gemeint war.
Jocke
6

Zum Zeitpunkt des Schreibens erhält JavaScript einen neuen Datentyp : BigInt. Es handelt sich um einen TC39-Vorschlag in Phase 4 , der in EcmaScript 2020 aufgenommen werden soll . BigIntist in Chrome 67+, FireFox 68+, Opera 54 und Node 10.4.0 verfügbar. Es ist in Safari et al. Im Gange ... Es führt numerische Literale mit dem Suffix "n" ein und ermöglicht eine beliebige Genauigkeit:

var a = 123456789012345678901012345678901n;

Die Präzision geht natürlich immer noch verloren, wenn eine solche Nummer (möglicherweise unbeabsichtigt) zu einem Nummer-Datentyp gezwungen wird.

Und natürlich wird es aufgrund des endlichen Speichers immer zeitliche Einschränkungen und zeitliche Kosten geben, um den erforderlichen Speicher zuzuweisen und mit so großen Zahlen zu rechnen.

Zum Beispiel wird die Erzeugung einer Zahl mit hunderttausend Dezimalstellen eine merkliche Verzögerung dauern, bis sie abgeschlossen ist:

console.log(BigInt("1".padEnd(100000,"0")) + 1n)

...Aber es funktioniert.

Trincot
quelle
4

Ich habe einen einfachen Test mit der Formel X- (X + 1) = -1 durchgeführt, und der größte Wert von XI, der für Safari, Opera und Firefox (getestet unter OS X) verwendet werden kann, ist 9e15. Hier ist der Code, den ich zum Testen verwendet habe:

javascript: alert(9e15-(9e15+1));
Raynet
quelle
1
Beachten Sie, dass 9e15 = 2 ^ 53 ist (siehe @ Jimmys Antwort).
Wedge
6
9e15 = 9000000000000000. 2 ^ 53 = 9007199254740992. Um pedantisch zu sein, ist 9e15 daher nur ungefähr gleich 2 ^ 53 (mit zwei signifikanten Ziffern).
Devios1
@chaiguy In 9000000000000000gibt es 1 signifikante Zahl. in `9007199254740992` gibt es 15 signifikante Zahlen.
Royi Namir
@RoyiNamir Ich möchte hier kein sinnloses Argument beginnen, aber 9000000000000000 hat 16 signifikante Ziffern. Wenn Sie nur 1 wollen, müsste es als 9x10 ^ 15 geschrieben werden.
Devios1
1
@chaiguy Nein, 9000000000000000wie es ist - hat 1SF. wo 90*10^14hat 2. ( sigfigscalculator.appspot.com ) & mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (unterer Abschnitt)
Royi Namir
3

Ich schreibe es so:

var max_int = 0x20000000000000;
var min_int = -0x20000000000000;
(max_int + 1) === 0x20000000000000;  //true
(max_int - 1) < 0x20000000000000;    //true

Gleiches gilt für int32

var max_int32 =  0x80000000;
var min_int32 = -0x80000000;
Jerome
quelle
3

Kommen wir zu den Quellen

Beschreibung

Die MAX_SAFE_INTEGERKonstante hat einen Wert von 9007199254740991(9.007.199.254.740.991 oder ~ 9 Billiarden). Der Grund für diese Zahl ist, dass JavaScript Gleitkomma-Zahlen mit doppelter Genauigkeit verwendet, wie in IEEE 754 angegeben, und nur Zahlen zwischen -(2^53 - 1)und sicher darstellen kann 2^53 - 1.

Sicher bezieht sich in diesem Zusammenhang auf die Fähigkeit, Ganzzahlen genau darzustellen und korrekt zu vergleichen. Zum Beispiel Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2wird als wahr ausgewertet, was mathematisch falsch ist. Weitere Informationen finden Sie unter Number.isSafeInteger () .

Da MAX_SAFE_INTEGERes sich um eine statische Eigenschaft von Number handelt , verwenden Sie sie immer als Number.MAX_SAFE_INTEGERund nicht als Eigenschaft eines von Ihnen erstellten Number- Objekts.

Browser-Kompatibilität

Geben Sie hier die Bildbeschreibung ein

simhumileco
quelle
0

Im in Google Chrome integrierten Javascript können Sie ungefähr 2 ^ 1024 aufrufen, bevor die Zahl als unendlich bezeichnet wird.

Tommy
quelle
-1

Scato wrotes:

Alles, was Sie für bitweise Operationen verwenden möchten, muss zwischen 0x80000000 (-2147483648 oder -2 ^ 31) und 0x7fffffff (2147483647 oder 2 ^ 31 - 1) liegen.

Die Konsole zeigt an, dass 0x80000000 gleich +2147483648 ist, 0x80000000 & 0x80000000 jedoch -2147483648

Hex-Dezimalstellen sind vorzeichenlose positive Werte, also 0x80000000 = 2147483648 - das ist mathematisch korrekt. Wenn Sie einen vorzeichenbehafteten Wert festlegen möchten, müssen Sie nach rechts verschieben: 0x80000000 >> 0 = -2147483648. Sie können stattdessen auch 1 << 31 schreiben.

SammieFox
quelle
-7

Firefox 3 scheint mit großen Zahlen kein Problem zu haben.

1e + 200 * 1e + 100 berechnet eine Geldstrafe von 1e + 300.

Safari scheint auch damit kein Problem zu haben. (Für die Aufzeichnung ist dies auf einem Mac, wenn jemand anderes beschließt, dies zu testen.)

Wenn ich zu dieser Tageszeit nicht mein Gehirn verloren habe, ist dies viel größer als eine 64-Bit-Ganzzahl.

Jishi
quelle
18
Es ist keine 64-Bit-Ganzzahl, sondern eine 64-Bit-Gleitkommazahl, von der 52/53 Bit der ganzzahlige Teil sind. es kann also bis zu 1e300 verarbeiten, jedoch nicht mit exakter Präzision.
Jimmy
4
Jimmy ist richtig. Versuchen Sie dies in Ihrem Browser oder in der JS-Befehlszeile:100000000000000010 - 1 => 100000000000000020
Ryan
-7

Node.js und Google Chrome scheinen beide 1024-Bit-Gleitkommawerte zu verwenden, also:

Number.MAX_VALUE = 1.7976931348623157e+308
TinyTimZamboni
quelle
1
-1: Die maximal darstellbare (nicht exakte Integral-) Zahl kann ~ 2 ^ 1024 sein, aber das bedeutet nicht, dass sie vom 64- Bit-Standard IEEE-754 abweichen.
Roy Tinker
2
MAX_INT? Meinst du MAX_VALUE?
Raul Guiu
3
Das ist das Maximum eines Gleitkommawertes . Es bedeutet nicht, dass Sie ein Int so lange speichern können
phuclv
1
Oder genauer gesagt, Sie können ein int nicht so lange zuverlässig speichern, ohne an Genauigkeit zu verlieren . 2^53wird als bezeichnet, MAX_SAFE_INTweil über diesem Punkt die Werte zu Näherungswerten werden, genauso wie Brüche.
IMSoP