Quelle est la plus haute valeur entière de JavaScript vers laquelle un nombre peut aller sans perdre la précision?

Est-ce défini par la langue? Est-il un maximum défini? Est-ce différent dans les différents navigateurs?

816
demandé sur Peter Mortensen 2008-11-21 01:47:54

21 réponses

+/- 9007199254740991

ECMA Section 8.5-Numbers

notez que tous les entiers positifs et négatifs dont la magnitude n'est pas supérieure à 2 53 sont représentables dans le type de nombre (en effet, l'entier 0 a deux représentations, +0 et -0).

ce sont des valeurs à virgule flottante à 64 bits, les plus la valeur intégrale est 2 53 -1, ou 9007199254740991 . Dans ES6, ce nombre est défini comme .MAX_SAFE_INTEGER .

notez que les opérateurs bitwise et les opérateurs shift fonctionnent sur des ints 32 bits, donc dans ce cas, l'entier max safe est 2 31 -1, ou 2147483647.


Faites le Test!
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

technique note au sujet du numéro 9007199254740992: il y a une représentation exacte IEEE-754 de cette valeur, et vous pouvez assigner et lire cette valeur à partir d'une variable, donc pour très soigneusement applications choisies dans le domaine des entiers inférieurs ou égaux à cette valeur, vous pourriez traiter cela comme une valeur maximale.

dans le cas général, vous devez traiter cette valeur IEEE-754 comme inexacte, parce qu'il est ambigu si elle encode la valeur logique 9007199254740992 ou 9007199254740993.

749
répondu Jimmy 2018-09-29 20:16:14

> = ES6: Number.MIN_SAFE_INTEGER; Number.MAX_SAFE_INTEGER;

< = ES5

de la référence : 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
412
répondu Peter Bailey 2018-03-01 19:10:40

il est 2 53 == 9 007 199 254 740 992. C'est parce que Number s sont stockées comme point flottant dans un mantissa 52-bit.

la valeur minimale est -2 53 .

Cela fait des choses amusantes qui se passe

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

et peut aussi être dangereux:)

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
}

"autres lectures: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html

105
répondu Vjeux 2014-10-15 07:10:22

en JavaScript, il y a un numéro appelé Infinity .

exemples:

(Infinity>100)
=> true

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

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

cela peut suffire pour certaines questions sur ce sujet.

53
répondu BananaNeil 2017-10-06 22:25:27

la réponse de Jimmy représente correctement le spectre entier continu JavaScript comme -9007199254740992 à 9007199254740992 inclusivement (désolé 9007199254740993, vous pourriez penser que vous êtes 9007199254740993, mais vous avez tort! démonstration ci-dessous ou dans jsfiddle ).

document.write(9007199254740993);

cependant, il n'y a pas réponse qui trouve / prouve cette programmatically( autre que celui CoolAJ86 évoqué dans sa réponse qui se terminerait en 28.56 ans ;), donc voici une façon un peu plus efficace de le faire (pour être précis, il est plus efficace d'environ 28.55999999999968312 ans :), avec un violon d'essai :

/**
 * 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);
37
répondu Briguy37 2018-01-04 14:57:45

Pour être sûr

var MAX_INT = 4294967295;

raisonnement

j'ai pensé que je serais intelligent et trouver la valeur à laquelle x + 1 === x avec une approche plus pragmatique.

ma machine ne peut compter que 10 millions par seconde... donc je posterai la réponse définitive dans 28.56 ans.

si vous ne pouvez pas attendre aussi longtemps, je suis prêt à parier que

  • la plupart de vos boucles ne fonctionne pas pour 28.56 ans
  • 9007199254740992 === Math.pow(2, 53) + 1 est une preuve suffisante de la
  • vous devez vous en tenir à 4294967295 qui est Math.pow(2,32) - 1 pour éviter les problèmes attendus avec bit-shifting

Trouver 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
répondu CoolAJ86 2012-01-25 02:57:21

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
28
répondu WaiKit Kung 2014-03-31 05:52:35

La réponse courte est: "ça dépend."

si vous utilisez des opérateurs bitwise n'importe où (ou si vous faites référence à la longueur d'un tableau), les plages sont:

non signé: 0…(-1>>>0)

signé: (-(-1>>>1)-1)…(-1>>>1)

(il arrive que les opérateurs bitwise et la longueur maximale d'un tableau soient limités à des entiers de 32 bits.)

si vous n'utilisez pas d'opérateurs bitwise ou travailler avec des longueurs de réseau:

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

ces limitations sont imposées par la représentation interne du type" nombre", qui correspond généralement à la représentation en virgule flottante de double précision IEEE 754. (Notez que contrairement aux entiers signés typiques, la grandeur de la limite négative est la même que la grandeur de la limite positive, en raison des caractéristiques de la représentation interne, qui comprend en fait une négatif 0!)

27
répondu danorton 2011-07-17 07:13:26

d'Autres peuvent avoir déjà donné la réponse générique, mais je pensais que ce serait une bonne idée de donner un moyen rapide de déterminer :

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

qui me donne 9007199254740992 en moins d'une milliseconde dans Chrome 30.

il va tester des puissances de 2 pour trouver lequel, quand "ajouté" 1, égale lui-même.

11
répondu Philippe97 2014-01-19 23:14:06

Tout ce que vous souhaitez utiliser pour les opérations bitwise doit se situer entre 0x80000000 (-2147483648 ou -2^31) et 0x7fffff (2147483647 ou 2^31 - 1).

la console vous dira que 0x80000000 égal +2147483648, mais 0x80000000 & 0x80000000 égal -2147483648.

6
répondu Scato 2017-10-06 22:25:53

beaucoup de réponses plus tôt montrent le résultat true de 9007199254740992 === 9007199254740992 + 1

dire que 9 007 199 254 740 991 est l'entier de sécurité max.

Que si nous continuons d'accumulation:

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

nous pourrions découvrir, parmi les nombres plus grands que 9 007 199 254 740 992 , seuls les nombres pairs sont représentable .

c'est une entrée pour expliquer comment double-précision format binaire 64 bits travailler sur ce. Regardons comment 9 007 199 254 740 992 être tenu (représenté) en utilisant ce format binaire.

nous partons de 4 503 599 627 370 496 avec la version brève du format d'abord:

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

sur le côté gauche de la flèche, nous avons valeur bit 1 , et un adjacent point radix , puis en multipliant 2^52 , nous déplacer à droite le point radix 52 étapes, et il va à la fin. Maintenant on a 4503599627370496 en binaire.

maintenant nous commençons à accumuler 1 à cette valeur jusqu'à ce que tous les bits sont mis à 1, ce qui égale 9 007 199 254 740 991 en décimal.

  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. 

maintenant, cause que dans double-précision format binaire 64 bits , il allo strictement 52 bits pour fraction, plus de bit est disponible pour transporter pour ajouter un plus 1, donc ce que nous pourrions faire est de mettre tous les bits à 0, et manipuler la partie exposant:

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

                          (+1)
                                     (radix point have 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 --| 

maintenant nous obtenons le 9 007 199 254 740 992 , et avec un nombre plus grand que ça, le format pourrait tenir est 2 fois de la fraction :

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

ainsi quand le nombre d'obtenir à plus de 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, seulement 4 fois de la fraction pouvaient être tenus:

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

Que Diriez-vous du nombre entre [ 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  --|

la valeur du bit 1 après le point radix est 2^-1 exactement. (=1/2, = 0.5) Ainsi, lorsque le nombre est inférieur à 4 503 599 627 370 496 (2^52), Il y a un bit disponible pour représenter les 1/2 fois de l'entier :

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

inférieure à 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"

et quelle est la gamme disponible de partie exposant ? le format allot 11 bits pour cela. Format complet de Wiki : (Pour plus de détails s'il vous plaît allez-y)

IEEE 754 Double Floating Point Format.svg

enter image description here

donc pour gagner 2^52 dans la partie exposant nous avons exactement besoin de définir e = 1075.

5
répondu Carr 2018-08-07 12:54:05

j'ai fait un test simple avec une formule, X-(X+1)=-1, et la plus grande valeur de X que je peux obtenir pour travailler sur Safari, Opera et Firefox (testé sur OS X) est 9e15. Voici le code que j'ai utilisé pour tester:

javascript: alert(9e15-(9e15+1));
3
répondu Raynet 2017-10-06 22:23:59

, Essayez:

maxInt = -1 >>> 1

dans Firefox 3.6 c'est 2^31 - 1.

3
répondu Martin Naatz 2017-10-06 22:24:29

Je l'écris comme ceci:

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

idem pour int32

var max_int32 =  0x80000000;
var min_int32 = -0x80000000;
1
répondu jerome 2014-09-25 14:29:12

dans le Google Chrome intégré javascript, vous pouvez aller à environ 2^1024 avant que le nombre est appelé infini.

0
répondu Tommy 2012-01-10 01:05:22

Scato écrit:

tout ce que vous voulez utiliser pour les opérations bitwise doit être entre 0x80000000 (-2147483648 ou -2^31) et 0x7fffff (2147483647 ou 2^31) - 1).

la console vous dira que 0x80000000 égale + 2147483648, mais 0x80000000 & 0x80000000 = -2147483648

Hex-décimales sont des valeurs positives non signées, donc 0x80000000 = 2147483648 - thats mathématiquement correct. Si vous voulez en faire une valeur signée, vous devez déplacer à droite: 0x80000000 >> 0 = -2147483648. Vous pouvez aussi écrire 1 < < 31 à la place.

0
répondu SammieFox 2016-12-24 18:34:55

nombre.MAX_VALUE représente la valeur numérique maximale représentée en JavaScript.

puisque personne ne semble l'avoir dit, dans le moteur v8 il y a une différence de comportement pour 31 bits nombre et nombre au-dessus de cela.

si vous avez 32 bits vous pouvez utiliser le premier bit pour dire au moteur javascript quel type est cette donnée et avoir les bits restants contiennent les données réelles. C'est ce que V8 fait comme une petite optimisation pour 31 bis numbers (ou utilisé pour faire, mes sources sont assez datées). Vous avez le dernier 31 bits étant la valeur du nombre et puis le premier bit indiquant au moteur si c'est un nombre ou une référence d'objet.

cependant si vous utilisez le numéro au-dessus de 31 bits alors les données ne seront pas à l'intérieur, le nombre sera encadré en 64 bits double et l'optimisation ne sera pas là.

le Ligne de fond, dans la vidéo ci-dessous, est:

préfèrent les valeurs numériques qui peuvent être représentées par 31bits signé entier.

0
répondu Ced 2017-06-18 12:35:41

Javascript ne supporte pas longtemps.

donc pour les valeurs normales qu'il peut représenter moins de 32 bits, il utilisera le type de conteneur int. pour des valeurs entières supérieures à 32 bits, son utilisation est double. Dans la représentation double, la partie entière est de 53 bits et le repos est de mantissa (pour conserver les informations en virgule flottante).

ainsi, vous pouvez utiliser 2^53 - 1 dont la valeur est 9007199254740991

vous pouvez accéder à la valeur à utiliser dans votre code par Number.MAX_SAFE_INTEGER

0
répondu Fisherman 2017-12-30 05:39:00

allons aux sources

Description

la constante MAX_SAFE_INTEGER a une valeur de 9007199254740991 (9,007,199,254,740,991 ou ~9 quadrillions). Le raisonnement derrière ce nombre est que JavaScript utilise double-précision des numéros de format à virgule flottante comme spécifié dans IEEE 754 et ne peut représenter en toute sécurité des numéros entre -(253 - 1) et 253 - 1 .

sûr dans ce contexte se réfère à la capacité de représenter des entiers exactement et de les comparer correctement. Par exemple, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 va évaluer à vrai, ce qui est mathématiquement incorrect. Voir Le Numéro .isSafeInteger () pour plus d'informations.

Parce que MAX_SAFE_INTEGER est une propriété statique de Nombre , vous pouvez toujours l'utiliser comme Number.MAX_SAFE_INTEGER , plutôt que comme une propriété d'un Number objet que vous avez créé.

compatibilité avec les navigateurs

enter image description here

0
répondu simhumileco 2018-07-18 09:29:25

Firefox 3 ne semble pas avoir de problème avec les nombres énormes.

1e+200 * 1e+100 calcule amende à 1e+300.

Safari ne semblent avoir aucun problème avec elle. (Pour mémoire, c'est sur un Mac, si quelqu'un d'autre décide de le tester.)

sauf si j'ai perdu mon cerveau à cette heure de la journée, c'est bien plus grand qu'un entier 64 bits.

-6
répondu jishi 2017-10-06 22:23:03

Node.js et Google Chrome semblent tous les deux utiliser des valeurs de 1024 bits à virgule flottante ainsi:

Number.MAX_VALUE = 1.7976931348623157e+308
-7
répondu TinyTimZamboni 2017-10-06 22:26:22