wake-up-neo.com

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

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

910
TALlama

+/- 9007199254740991

ECMA Abschnitt 8.5 - Zahlen

Beachten Sie, dass alle positiven und negativen ganzen Zahlen, deren Größe nicht größer als 2 ist53 sind im Zahlentyp darstellbar (in der Tat hat die Ganzzahl 0 zwei Darstellungen, +0 und –0).

Es handelt sich um 64-Bit-Gleitkommawerte, der größte exakte Integralwert ist 253-1 oder 9007199254740991. In ES6 ist dies definiert als Number.MAX_SAFE_INTEGER .

Beachten Sie, dass die bitweisen Operatoren und die Shift-Operatoren mit 32-Bit-Ints arbeiten. In diesem Fall ist die maximale sichere Ganzzahl 231-1 oder 2147483647.


var x = 9007199254740992;
var y = -x;
x == x + 1; // true !
y == y - 1; // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:
x / 2;      // 4503599627370496
x >> 1;     // 0
x | 1;      // 1

Technischer Hinweis zum Thema der Nummer 9007199254740992: Es gibt eine genaue IEEE-754-Darstellung dieses Wertes, und Sie können diesen Wert einer Variablen zuweisen und auslesen, also für sehr sorgfältig Bei ausgewählten Anwendungen im Bereich von ganzen Zahlen, die kleiner oder gleich diesem Wert sind, können Sie dies als Maximalwert behandeln.

Im Allgemeinen müssen Sie diesen IEEE-754-Wert als ungenau behandeln, da es nicht eindeutig ist, ob der logische Wert 9007199254740992 oder 9007199254740993 codiert wird.

826
Jimmy

> = ES6:

Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;

<= ES5

Von die Referenz :

Number.MAX_VALUE;
Number.MIN_VALUE;
console.log('MIN_VALUE', Number.MIN_VALUE);
console.log('MAX_VALUE', Number.MAX_VALUE);

console.log('MIN_SAFE_INTEGER', Number.MIN_SAFE_INTEGER); //ES6
console.log('MAX_SAFE_INTEGER', Number.MAX_SAFE_INTEGER); //ES6
451
Peter Bailey

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

Der min Wert ist -253.

Dadurch passieren einige lustige Dinge

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
}

Weitere Informationen: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html

108
Vjeux

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.

53
BananaNeil

Jimmys Antwort stellt das kontinuierliche JavaScript-Ganzzahlspektrum korrekt als - 9007199254740992 bis 9007199254740992 inklusive (sorry 9007199254740993, du denkst vielleicht du bist 9007199254740993, aber du liegst falsch! Demonstration unten oder in jsfiddle).

document.write(9007199254740993);

Es gibt jedoch keine Antwort, die dies programmatisch findet/beweist (anders als diejenige, auf die CoolAJ86 in seine Antwort anspielt, die in 28,56 Jahren enden würde;). Hier ist also ein etwas effizienterer Weg, dies zu tun ( um genau zu sein, ist es um ungefähr 28.559999999968312 Jahre effizienter :), zusammen mit einem Testgeige :

/**
 * 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);
40
Briguy37

Sicher sein

var MAX_INT = 4294967295;

Argumentation

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

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

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

  • Die meisten Ihrer Loops haben eine Laufzeit von 28,56 Jahren
  • 9007199254740992 === Math.pow(2, 53) + 1 ist Beweis genug
  • Sie sollten sich an 4294967295 halten, was Math.pow(2,32) - 1 ist, um zu erwartende Probleme mit der Bitverschiebung zu vermeiden

Suche nach 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);
}());
32
CoolAJ86

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
28
WaiKit Kung

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:

Vorzeichenlos: 0…(-1>>>0)

Signiert: (-(-1>>>1)-1)…(-1>>>1)

(Es kommt 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:

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

Diese Einschränkungen werden durch die interne Darstellung des Typs "Number" auferlegt, die im Allgemeinen der Gleitkommadarstellung nach IEEE 754 mit doppelter Genauigkeit entspricht. (Beachten Sie, dass im Gegensatz zu typischen Ganzzahlen mit Vorzeichen die Größe des negativen Grenzwerts der Größe des positiven Grenzwerts entspricht, da die interne Darstellung ein negatives 0 enthält!)

27
danorton

Viele frühere Antworten zeigen das Ergebnis true von 9007199254740992 === 9007199254740992 + 1
um zu überprüfen, ob 9 007 199 254 740 991 die maximale sichere Ganzzahl 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 bei Zahlen größer als 9 007 199 254 740 992 nur gerade Zahlen darstellbar sind.

Hier erfahren Sie, wie 64-Bit-Binärformat mit doppelter Genauigkeit dies funktioniert. Schauen wir uns an, wie 9 007 199 254 740 992 unter Verwendung dieses Binärformats gehalten (dargestellt) wird.

Wir beginnen mit 4 503 599 627 370 496 mit der kurzen Version des Formats zuerst:

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

Auf der Seite vor dem Pfeil haben wir Bitwert 1 und einen angrenzenden Radixpunkt , dann bewegen wir den Radixpunkt durch Multiplizieren von 2^52 um 52 Schritte nach rechts und gehen zum Ende. Jetzt erhalten wir 4503599627370496 in binärer Form.

Jetzt akkumulieren wir 1 zu diesem Wert, 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 dieses Bit im 64-Bit-Binärformat mit doppelter Genauigkeit ausschließlich 52 Bit für Brüche zuweist, ist kein Bit mehr verfügbar, um eine weitere 1 hinzuzufügen. Wir können also alle Bits auf zurücksetzen 0, und manipulieren Sie 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 erhalten wir das 9 007 199 254 740 992 , und mit einer höheren Zahl könnte das Format das 2-fache des Bruchs enthalten. Das bedeutet, dass jetzt jede 1-Addition auf dem Bruchteil der 2-Addition entspricht. Deshalb kann 64-Bit-Binärformat mit doppelter Genauigkeit keine ungeraden Zahlen enthalten, wenn die Zahl größer als 9 007 ist 199 254 740 992 :

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

Wenn die Zahl also größer als 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984 ist, kann nur das 4-fache des Bruchs 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 Darstellung zur Verfügung das 1/2-fache der ganzen Zahl :

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 von Exponententeil ? Das Format sieht dafür 11 Bit vor. Vollständiges Format aus Wiki : (Für weitere Informationen gehen Sie bitte dorthin)

IEEE 754 Double Floating Point Format.svg

enter image description here

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

14
Carr

Andere haben vielleicht bereits die generische Antwort gegeben, aber ich dachte, es wäre eine gute Idee, einen schnellen Weg zu finden, um dies festzustellen:

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 wird Potenzen von 2 testen, um herauszufinden, welche, wenn sie zu 1 addiert werden, sich selbst entspricht.

11
Philippe97

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 teilt Ihnen mit, dass 0x80000000 +2147483648 entspricht, aber 0x80000000 & 0x80000000 -2147483648 entspricht.

7
Scato

Versuchen:

maxInt = -1 >>> 1

In Firefox 3.6 ist es 2 ^ 31 - 1.

5
Martin Naatz

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

javascript: alert(9e15-(9e15+1));
4
Raynet

Kommen wir zu den Quellen

Beschreibung

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

Sicher bezieht sich in diesem Zusammenhang auf die Fähigkeit, ganze Zahlen genau darzustellen und richtig zu vergleichen. Beispielsweise wird Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 mit true ausgewertet, was mathematisch falsch ist. Weitere Informationen finden Sie unter Number.isSafeInteger () .

Da MAX_SAFE_INTEGER eine statische Eigenschaft von Number ist, verwenden Sie sie immer als Number.MAX_SAFE_INTEGER und nicht als Eigenschaft eines von Ihnen erstellten Number -Objekts.

Browser-Kompatibilität

enter image description here

2
simhumileco

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;
1
jerome

Zur Zeit erhält JavaScript einen neuen Datentyp: BigInt. Es ist ein TC39-Vorschlag zu Stufe . BigInt ist in Chrome 67+, FireFox 67+ (erfordert eine Option zum Aktivieren), Opera 54 und Node 10.4.0 verfügbar. Es ist in Safari ua im Gange. Es führt numerische Literale mit dem Suffix "n" ein und ermöglicht eine willkürliche Genauigkeit:

var a = 123456789012345678901012345678901n;

Die Genauigkeit geht natürlich immer noch verloren, wenn eine solche Zahl (möglicherweise unbeabsichtigt) in einen Zahlendatentyp umgewandelt wird.

1
trincot

In dem in Google Chrome integrierten Javascript können Sie zu ungefähr 2 ^ 1024 wechseln, bevor die Zahl Unendlich heißt.

1
Tommy
0
Marwen Trabelsi

Number.MAX_VALUE repräsentiert den maximalen numerischen Wert, der in JavaScript darstellbar ist.

Da dies anscheinend niemand gesagt hat, gibt es in der v8 Engine einen Unterschied im Verhalten für 31 bits Nummer und Nummer darüber.

Wenn Sie 32 bits haben, können Sie das erste Bit verwenden, um der Javascript-Engine mitzuteilen, welcher Typ diese Daten sind, und die verbleibenden Bits enthalten die tatsächlichen Daten. Das ist, was V8 als kleine Optimierung für 31 bisnumbers tut (oder früher, meine Quellen sind ziemlich veraltet). Sie haben den letzten 31 bits als Zahlenwert und dann das erste Bit, das der Engine mitteilt, ob es sich um eine Zahl oder eine Objektreferenz handelt.

Wenn Sie jedoch eine Zahl oberhalb von 31 bits verwenden, passen die Daten nicht, die Zahl wird doppelt in 64-Bit-Felder geschrieben und die Optimierung ist nicht vorhanden.

Das Fazit im Video unten lautet:

bevorzugen Sie numerische Werte, die als vorzeichenbehaftete 31-Bit-Ganzzahlen dargestellt werden können.

0
Ced

Wenn die Zahl größer als 2 ist, um die Potenz 53 dh.

Math.pow(2, 53)

Das Javascript kennt es als eine große ganze Zahl. Dann speichert Javascript sie als 'bigint', so dass der Vergleich mit 'bigint'==='bigint' wahr wird.

Sichereres Speichern ihrer Werte im Math-Objekt.

const bigInt1 = Math.pow(2, 55)
const bigInt2 = Math.pow(2, 66)
console.log(bigInt1 === bigInt2) // false
0

Scato schreibt:

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 teilt Ihnen mit, dass 0x80000000 +2147483648 entspricht, aber 0x80000000 & 0x80000000 -2147483648 entspricht

Hexadezimalzahlen sind vorzeichenlose positive Werte, also 0x80000000 = 2147483648 - das ist mathematisch korrekt. Wenn Sie einen vorzeichenbehafteten Wert festlegen möchten, müssen Sie die rechte Umschalttaste drücken: 0x80000000 >> 0 = -2147483648. Sie können stattdessen auch 1 << 31 schreiben.

0
SammieFox

Grundsätzlich unterstützt Javascript nicht lange.
Für normale Werte, die weniger als 32 Bit darstellen können, wird der Container vom Typ int verwendet. Für ganzzahlige Werte größer als 32 Bit wird double verwendet. Bei der doppelten Darstellung ist der ganzzahlige Teil 53 Bit und der Rest ist die Mantisse (um Gleitkommainformationen beizubehalten).
so können Sie 2^53 - 1 verwenden, dessen Wert 9007199254740991 ist
Sie können auf den in Ihrem Code zu verwendenden Wert zugreifen, indem Sie Number.MAX_SAFE_INTEGER

0
Fisherman