2016-07-07 1 views
1
ce code

Tenir compte (nœud v5.0.0)Comment javascript traite les grands entiers (plus de 52 bits)?

const a = Math.pow(2, 53) 
const b = Math.pow(2, 53) + 1 
const c = Math.pow(2, 53) + 2 

console.log(a === b) // true 
console.log(a === c) // false 

Pourquoi a === b est vrai?

Quelle est la valeur maximale que javascript peut gérer? J'implémente un générateur d'entiers aléatoires jusqu'à 2^64. Y at-il un piège que je devrais être au courant de?

+1

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_VALUE –

+0

Désolé, déjà corrigé. – user1518183

+0

a et b sont le même nombre, et les mêmes numéros sont identiques ou égaux. – dandavis

Répondre

1

. :: JavaScript ne prend en charge que les entiers 53 bits ::.

Tous les nombres en virgule flottante sont JavaScript qui signifie que les nombres entiers sont toujours représentés comme

sign × mantissa × 2exponent 

La mantisse a 53 bits. Vous pouvez utiliser l'exposant pour obtenir des entiers plus élevés, mais ils ne seront plus contigus. Par exemple, vous devez généralement multiplier la mantisse par deux (exposant 1) pour atteindre le 54ème bit.

Cependant, si vous multipliez par deux, vous ne serez en mesure de représenter chaque seconde entier:

Math.pow(2, 53)  // 54 bits 9007199254740992 
Math.pow(2, 53) + 1 // 9007199254740992 
Math.pow(2, 53) + 2 //9007199254740994 
Math.pow(2, 53) + 3 //9007199254740996 
Math.pow(2, 53) + 4 //9007199254740996 

ont été arrondis au cours de l'ajout font des choses imprévisibles pour des incréments impairs (+1 par rapport à +3). La représentation réelle est un peu plus compliquée mais cette explication devrait vous aider à comprendre le problème de base.

Vous pouvez utiliser en toute sécurité la bibliothèque strint pour coder de grands entiers dans des chaînes et effectuer des opérations arithmétiques sur celles-ci.

Here est l'article complet.

3

répondre à votre deuxième question, voici le maximum entier en toute sécurité en JavaScript:

console.log(Number.MAX_SAFE_INTEGER); 

Tout le reste est écrit dans MDN:

La constante MAX_SAFE_INTEGER a une valeur de 9007199254740991. Le raisonnement derrière ce nombre est que JavaScript utilise double précision nombres à virgule flottante comme spécifié dans IEEE 754 et ne peut que représenter en toute sécurité les numéros entre -(253 - 1) et 253 - 1.

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

2

Comment javascript traite les grands entiers?

JS n'a pas d'entiers. Les numéros JS sont des flottants de 64 bits. Ils sont stockés comme une mantisse et un exposant.

La précision est donnée par la mantisse, la grandeur par l'exposant.

Si votre numéro a besoin de plus de précision que ce qui peut être stocké dans la mantisse, les bits les moins significatifs seront tronqués.

9007199254740992; // 9007199254740992 
(9007199254740992).toString(2); 
// "100000000000000000000000000000000000000000000000000000" 
// \  \     ...     /\ 
// 1  10          53 54 
// The 54-th is not stored, but is not a problem because it's 0 

9007199254740993; // 9007199254740992 
(9007199254740993).toString(2); 
// "100000000000000000000000000000000000000000000000000000" 
// \  \     ...     /\ 
// 1  10          53 54 
// The 54-th bit should be 1, but the mantissa only has 53 bits! 

9007199254740994; // 9007199254740994 
(9007199254740994).toString(2); 
// "100000000000000000000000000000000000000000000000000010" 
// \  \     ...     /\ 
// 1  10          53 54 
// The 54-th is not stored, but is not a problem because it's 0 

Ensuite, vous pouvez stocker tous ces entiers:

-9007199254740992, -9007199254740991, ..., 9007199254740991, 9007199254740992 

Le second est appelé le minimum safe integer:

La valeur de Number.MIN_SAFE_INTEGER est l'entier n tel plus petit que n et n - 1 sont tous les deux exactement représentables en tant que valeur numérique.

La valeur de Number.MIN_SAFE_INTEGER est -9007199254740991 (- (2 -1)).

Le second dernier est appelé maximum safe integer:

La valeur de Number.MAX_SAFE_INTEGER est le plus grand entier n tel que n et n + 1 sont tous deux exactement représentable en tant que valeur numérique.

La valeur de Number.MAX_SAFE_INTEGER est 9007199254740991 (2 -1).

0

Number.MAX_VALUE vous indiquera la plus grande valeur à virgule flottante représentable dans votre implémentation JS. La réponse sera probablement: 1.7976931348623157e + 308. Mais cela ne veut pas dire que tous les entiers jusqu'à 10^308 peuvent être représentés exactement. Comme le montre votre exemple de code, au-delà de 2^53, seuls les nombres pairs peuvent être représentés, et au fur et à mesure que vous avancez sur la ligne numérique, les écarts deviennent beaucoup plus larges.

Si vous avez besoin d'entiers exacts supérieurs à 2^53, vous voudrez probablement travailler avec un paquet bignum, qui permet des entiers arbitrairement grands (dans les limites de la mémoire disponible). Deux paquets que je connais sont:

BigInt by Leemon

et

Crunch