Les nombres en JavaScript sont à virgule flottante binaire double précision IEEE-754, un format assez compact (64 bits) qui permet des calculs rapides et une vaste plage. Il le fait en stockant le nombre sous forme de bit de signe, d'exposant de 11 bits et de significande de 52 bits (bien que grâce à son intelligence, il obtienne en fait 53 bits de précision). C'est une virgule flottante binaire (base 2): le significande (plus une certaine intelligence) nous donne la valeur, et l'exposant nous donne la grandeur du nombre.
Naturellement, avec juste autant de bits significatifs, tous les nombres ne peuvent pas être stockés. Voici le numéro 1, et le numéro suivant le plus élevé après 1 que le format peut stocker, 1 + 2 -52 ≈ 1.00000000000000022, et le prochain plus élevé après cela 1 + 2 × 2 -52 ≈ 1.00000000000000044:
+ ------------------------------------------------- -------------- signe bit
/ + ------- + ---------------------------------------- -------------- exposant
/ / | + ------------------------------------------------- + - significand
/ / | / |
0 01111111111 0000000000000000000000000000000000000000000000000000
= 1
0 01111111111 0000000000000000000000000000000000000000000000000001
≈ 1.00000000000000022
0 01111111111 0000000000000000000000000000000000000000000000000010
≈ 1.00000000000000044
Notez le saut de 1.00000000000000022 à 1.00000000000000044; il n'y a aucun moyen de stocker 1.0000000000000003. Cela peut également se produire avec des entiers: Number.MAX_SAFE_INTEGER(9,007,199,254,740,991) est la valeur entière positive la plus élevée que le format peut contenir où iet i + 1sont tous les deux exactement représentables ( spec ). 9 007 199 254 740 991 et 9 007 199 254 740 992 peuvent être représentés, mais l' entier suivant , 9 007 199 254 740 993, ne le peut pas; le prochain entier que nous pouvons représenter après 9,007,199,254,740,992 est 9,007,199,254,740,994. Voici les modèles de bits, notez le bit le plus à droite (le moins significatif):
+ ------------------------------------------------- -------------- signe bit
/ + ------- + ---------------------------------------- -------------- exposant
/ / | + ------------------------------------------------- + - significand
/ / | / |
0 10000110011 1111111111111111111111111111111111111111111111111111
= 9007199254740991 (Numéro.MAX_SAFE_INTEGER)
0 10000110100 0000000000000000000000000000000000000000000000000000
= 9007199254740992 (Numéro.MAX_SAFE_INTEGER + 1)
x xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
9007199254740993 (Number.MAX_SAFE_INTEGER + 2) ne peut pas être stocké
0 10000110100 0000000000000000000000000000000000000000000000000001
= 9007199254740994 (Numéro.MAX_SAFE_INTEGER + 3)
Souvenez-vous que le format est en base 2, et avec cet exposant, le bit le moins significatif n'est plus fractionnaire; il a une valeur de 2. Il peut être désactivé (9 007 199 254 740 992) ou activé (9 007 199 254 740 994); donc à ce stade, nous avons commencé à perdre de la précision même à l'échelle des nombres entiers (entiers). Ce qui a des implications pour notre boucle!
Après avoir terminé la i = 9,007,199,254,740,992boucle, i++nous donne ... à i = 9,007,199,254,740,992nouveau; il n'y a pas de changement i, car le prochain entier ne peut pas être stocké et le calcul finit par arrondir vers le bas. ichangerait si nous le faisions i += 2, mais i++ne pouvons pas le changer. Nous avons donc atteint un état stable: ine change jamais et la boucle ne se termine jamais.