Номери в JavaScript - це двоканальна плаваюча точка з двома точністю IEEE-754, досить компактний формат (64 біт), який забезпечує швидкі обчислення та широкий діапазон. Це робиться, зберігаючи число як бітовий знак, 11-бітний показник і 52-розрядне значення (хоча завдяки кмітливості він фактично отримує 53 біт точності). Це двійкова плаваюча точка (основа 2): Значення (плюс деяка кмітливість) дає нам значення, а показник дає нам величину числа.
Звичайно, маючи так багато значущих бітів, не кожне число може бути збережене. Ось число 1 і наступне найбільше число після 1, яке може зберігати формат, 1 + 2 -52 ≈ 1.00000000000000022, а наступне найвище після цього 1 + 2 × 2 -52 ≈ 1.00000000000000044:
+ ------------------------------------------------- -------------- знак біт
/ + ------- + ---------------------------------------- -------------- показник
/ / | + ------------------------------------------------- + - значущеі
/ / | / |
0 01111111111 000000000000000000000000000000000000000000000000000000000000
= 1
0 01111111111 000000000000000000000000000000000000000000000000000000000001
≈ 1.00000000000000022
0 01111111111 000000000000000000000000000000000000000000000000000000000010
≈ 1.00000000000000044
Зверніть увагу на стрибок з 1.00000000000000022 до 1.00000000000000044; немає можливості зберігати 1.0000000000000003. Це може трапитися з цілими числами, теж: Number.MAX_SAFE_INTEGER(9,007,199,254,740,991) є найвищим позитивним цілим значенням , що формат може містити де iі i + 1обидва точно представима ( специфікація ). Як 9,007,199,254,740,991, так і 9,007,199,254,740,992 можна представити, але наступне ціле число, 9,007,199,254,740,993, не може; наступне ціле число, яке ми можемо представити після 9,007,199,254,740,992, становить 9,007,199,254,740,994. Ось бітові шаблони, зверніть увагу на крайній правий (найменш значущий) біт:
+ ------------------------------------------------- -------------- знак біт
/ + ------- + ---------------------------------------- -------------- показник
/ / | + ------------------------------------------------- + - значущеі
/ / | / |
0 10000110011 111111111111111111111111111111111111111111111111111111
= 9007199254740991 (Кількість.MAX_SAFE_INTEGER)
0 10000110100 00000000000000000000000000000000000000000000000000000000
= 9007199254740992 (Кількість.MAX_SAFE_INTEGER + 1)
x xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
9007199254740993 (Number.MAX_SAFE_INTEGER + 2) не можна зберігати
0 10000110100 00000000000000000000000000000000000000000000000000000001
= 9007199254740994 (Кількість.MAX_SAFE_INTEGER + 3)
Пам'ятайте, що формат - це база 2, і з цим показником найменш значущий біт вже не дробовий; вона має значення 2. Може бути вимкнено (9,007,199,254,740,992) або увімкнено (9,007,199,254,740,994); тож у цей момент ми почали втрачати точність навіть за цілою шкалою чисел. Що має значення для нашого циклу!
Закінчивши i = 9,007,199,254,740,992цикл, i++дає нам ... i = 9,007,199,254,740,992знову; немає змін i, оскільки наступне ціле число не може бути збережене, і обчислення закінчується округленням вниз. iзмінився б, якби ми i += 2, але i++не можемо змінити. Отже, ми дійшли до стаціонарного стану: iніколи не змінюється, і цикл ніколи не припиняється.