web-dev-qa-db-fra.com

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

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

910
TALlama

+/- 9007199254740991

ECMA Section 8.5 - Nombres

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

Ce sont des valeurs à virgule flottante de 64 bits, la valeur intégrale exacte la plus grande étant 253-1 ou 9007199254740991. Dans ES6, ceci est défini comme Number.MAX_SAFE_INTEGER .

Notez que les opérateurs au niveau des bits et les opérateurs de décalage fonctionnent sur des ints de 32 bits, de sorte que dans ce cas, le nombre entier sécurisé maximal est 2.31-1 ou 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

Note technique sur le numéro 9007199254740992: Il existe une représentation exacte de cette valeur selon IEEE-754, et vous pouvez affecter et lire cette valeur à partir d'une variable, donc pour très attentivement applications choisies dans le domaine des entiers inférieurs ou égaux à cette valeur, vous pouvez traiter cela comme une valeur maximale.

Dans le cas général, vous devez traiter cette valeur IEEE-754 comme inexacte, car il est ambigu de savoir si elle code la valeur logique 9007199254740992 ou 9007199254740993.

826
Jimmy

> = 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
451
Peter Bailey

Il est 253 == 9 007 199 254 740 992. Cela est dû au fait que Numbers sont stockés en tant que virgule flottante dans une mantisse de 52 bits.

La valeur minimale est -253.

Cela fait des choses amusantes

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
}

Lectures supplémentaires: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html

108
Vjeux

En JavaScript, il existe 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 concernant ce sujet.

53
BananaNeil

La réponse de Jimmy représente correctement le spectre entier JavaScript continu sous la forme - 9007199254740992 en 9007199254740992 inclus (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, aucune réponse n’est trouvée/prouvée par le programme (autre que celle mentionnée par CoolAJ86 dans sa réponse qui se terminerait dans 28,56 ans;). Voici donc un moyen légèrement plus efficace de le faire ( pour être précis, il est plus efficace d’environ 28,559999999968312 ans :), avec un test de violon :

/**
 * 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

Pour être sûr

var MAX_INT = 4294967295;

Raisonnement

Je pensais être intelligent et trouver la valeur à laquelle x + 1 === x avec une approche plus pragmatique.

Ma machine ne peut compter que 10 millions par seconde environ ... alors je vous répondrai avec 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 courent pas avant 28,56 ans
  • 9007199254740992 === Math.pow(2, 53) + 1 est une preuve suffisante
  • Vous devriez vous en tenir à 4294967295 qui est Math.pow(2,32) - 1 afin d'éviter les problèmes attendus avec le transfert de bits

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
CoolAJ86

ECMAScript 6:

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

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

Si vous utilisez des opérateurs au niveau des bits n’importe où (ou si vous faites référence à la longueur d’un tableau), les plages sont les suivantes:

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

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

(Il se trouve que les opérateurs au niveau des bits et la longueur maximale d'un tableau sont limités à des entiers 32 bits.)

Si vous n’utilisez pas d’opérateurs au niveau des bits ou ne travaillez pas avec des longueurs de tableau:

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

Ces limitations sont imposées par la représentation interne de type "Number", qui correspond généralement à la représentation à virgule flottante double précision IEEE 754. (Notez que, contrairement aux nombres entiers signés typiques, l’ampleur de la limite négative est identique à l’amplitude de la limite positive, en raison des caractéristiques de la représentation interne, qui inclut en fait un négatif 0!)

27
danorton

Plusieurs réponses précédentes montrent le résultat true de 9007199254740992 === 9007199254740992 + 1
pour vérifier que 9 007 199 254 740 991 est le nombre entier de sécurité maximal.

Et si nous continuons à faire de l'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 avons découvert que parmi les nombres supérieurs à 9 007 199 254 740 992 , seuls les nombres pairs sont représentable .

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

Nous commençons par 4 503 599 627 370 496 avec la version brève du format en premier:

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

Sur le côté avant la flèche, nous avons la valeur du bit 1 et un point de radix adjacent , puis en multipliant 2^52, nous déplaçons le point de base de 52 pas et il va jusqu'au bout. Nous obtenons maintenant 4503599627370496 en binaire.

Maintenant, nous commençons à accumuler 1 à cette valeur jusqu'à ce que tous les bits soient mis à 1, ce qui équivaut à 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, parce que dans le format binaire 64 bits à double précision , il attribue strictement 52 bits pour la fraction, aucun autre bit n'est disponible pour l'ajout d'un plus 1, nous pouvons donc remettre 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 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 --| 

Maintenant nous obtenons le 9 007 199 254 740 992 , et avec un nombre supérieur à ce que Le format pourrait contenir est 2 fois la fraction , cela signifie maintenant que chaque ajout de 1 sur la partie fraction équivaut en fait à 2 addition, voilà pourquoi Le format binaire double précision 64 bits ne peut pas contenir de nombres impairs lorsque le nombre est supérieur à 9 007 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 --|

Ainsi, lorsque le nombre dépasse 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, seules 4 fois la fraction peuvent être tenue:

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 de base est 2 ^ -1 exactement. (= 1/2, = 0.5) Donc, lorsque le nombre inférieur à 4 503 599 627 370 496 (2 ^ 52), il y a un bit disponible pour représenter le 1/2 fois de l'entier :

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

Inférieur à 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 plage disponible de partie exposant ? le format alloue 11 bits pour cela. Format complet de Wiki : (pour plus de détails, allez-y)

IEEE 754 Double Floating Point Format.svg

enter image description here

Donc, pour que l'exposant soit 2 ^ 52, nous devons définir e = 1075.

14
Carr

Autre peut-être déjà donné la réponse générique, mais j’ai pensé que ce serait une bonne idée de donner un moyen rapide de le déterminer:

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

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

Il testera les puissances de 2 pour trouver lequel, quand 'ajouté' 1, est égal à lui-même.

11
Philippe97

Tout ce que vous voulez utiliser pour les opérations au niveau des bits doit être compris entre 0x80000000 (-2147483648 ou -2 ^ 31) et 0x7fffffff (2147483647 ou 2 ^ 31 - 1).

La console vous dira que 0x80000000 est égal à +2147483648, mais que 0x80000000 & 0x80000000 est égal à -2147483648.

7
Scato

Essayer:

maxInt = -1 >>> 1

Dans Firefox 3.6, c'est 2 ^ 31 - 1.

5
Martin Naatz

J'ai fait un test simple avec une formule, X- (X + 1) = - 1, et la plus grande valeur de XI peut fonctionner 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));
4
Raynet

Passons au sources

La description

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

Coffre-fort dans ce contexte fait référence à la possibilité de représenter des nombres entiers avec exactitude et de les comparer correctement. Par exemple, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 sera évalué à true, ce qui est mathématiquement incorrect. Voir Number.isSafeInteger () pour plus d'informations.

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

Compatibilité du navigateur

enter image description here

2
simhumileco

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
jerome

Au moment de l'écriture, JavaScript reçoit un nouveau type de données: BigInt. C'est une proposition de TC39 à étape . BigInt est disponible dans Chrome 67+, FireFox 67+ (nécessite une option pour l'activer), Opera 54 et Node 10.4.0. Il est en cours dans Safari, et al ... Il introduit des littéraux numériques ayant un suffixe "n" et permet une précision arbitraire:

var a = 123456789012345678901012345678901n;

La précision sera toujours perdue, bien sûr, quand un tel nombre est (peut-être involontairement) contraint à un type de données numérique.

1
trincot

Dans le javascript intégré à Google Chrome, vous pouvez accéder à environ 2 ^ 1024 avant que le nombre ne s'appelle infini.

1
Tommy
0
Marwen Trabelsi

Number.MAX_VALUE représente la valeur numérique maximale pouvant être représentée en JavaScript.

Comme personne ne semble l'avoir dit, dans le moteur v8 , il existe une différence de comportement pour 31 bits nombre et nombre supérieur à celui-ci.

Si vous avez 32 bits, vous pouvez utiliser le premier bit pour indiquer au moteur javascript le type de ces données et pour que les bits restants contiennent les données réelles. C'est ce que V8 fait comme une petite optimisation pour 31 bisnumbers (ou l'habitude de le faire, mes sources sont assez datées). Vous avez le dernier 31 bits étant le nombre, puis le premier bit indiquant au moteur s'il s'agit d'un nombre ou d'une référence d'objet.

Toutefois, si vous utilisez un nombre supérieur à 31 bits, alors les données ne rentrent pas dans la liste, le nombre sera encadré en double de 64 bits et l'optimisation n'y sera pas.

La ligne du bas, dans la vidéo ci-dessous, est:

préférez les valeurs numériques pouvant être représentées sous la forme 31 bits entiers signés.

0
Ced

Lorsque le nombre est supérieur à 2 à la puissance 53, c.-à-d.

Math.pow(2, 53)

Le javascript le connaît comme un grand entier. Ensuite, javascript les stocke en tant que 'bigint' afin que la comparaison avec 'bigint'==='bigint' devienne vraie.

Un moyen plus sûr de stocker leurs valeurs dans l'objet Math lui-même.

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

Scato écrit:

tout ce que vous voulez utiliser pour les opérations au niveau des bits doit être compris entre 0x80000000 (-2147483648 ou -2 ^ 31) et 0x7fffffff (2147483647 ou 2 ^ 31 - 1).

la console vous dira que 0x80000000 est égal à +2147483648, mais 0x80000000 et 0x80000000 est égal à -2147483648.

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

0
SammieFox

En gros, javascript ne supporte pas longtemps.
Ainsi, pour les valeurs normales pouvant représenter moins de 32 bits, il utilisera le conteneur de type int. pour les valeurs entières supérieures à 32 bits, son utilisation est double. En double représentation, la partie entière est de 53 bits et reste est une mantisse (pour conserver les informations en virgule flottante).
afin que vous puissiez 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
Fisherman