Почему JS самостоятельно изменяет числа?

В learn.js приводится пример:
alert( 9999999999999999 ); // покажет 10000000000000000

В учебнике говорится, что причина такому поведению в том, что отведенных 52 бит не хватает на цифры. Я не понимаю. По идее, вроде бы если не хватает памяти, число наоборот должно уменьшаться, а не увеличиваться как это происходит в примере выше (было 16, стало 17 знаков).

P.S. И кстати, вроде бы если числу не хватает отведенной ему памяти, должно выводить Infinity. Почему в этом случае не выводится Infinity?

Может кто-нибудь получше объяснить как это работает?
  • Вопрос задан
  • 262 просмотра
Решения вопроса 1
dollar
@dollar
Делай добро и бросай его в воду.
Условно происходит округление.

На пальцах это выглядит примерно так. В памяти есть место для хранения целого числа, а также есть место для его порядка (степени). Размер первого места задаёт, сколько цифр может быть в числе, например 17 (но это примерно, потому что там биты, то есть число хранится в двоичной системе). Порядок же позволяет дописать очень много нулей к числу справа или слева. Количество нулей тоже не бесконечно, но очень большое, всем хватит.

Поэтому для очень широких чисел типа такого:
1230000000000000099999999999999999999999999999999
невозможно сохранить все цифры в точности. Оно просто не влезает в целую часть. Приходится брать за основу какой-то отрезок из 17 цифр. Очевидно, что логичнее начинать со старших разрядов:
12300000000000000 (17 цифр)
Ну а дальше встаёт вопрос, что делать с младшими? Порядок (степень) можно примерно сохранить, дописав нули. И в случае, если отбрасываем .....999999, то логичнее перевести единичку в следующий разряд. Получится:
1230000000000000100000000000000000000000000000000
(т.е. 1.2300000000000001e+48)

Повторюсь, это примерно, без подробностей, для общего понимания. На самом деле там куча нюансов.
0.1 + 0.2 == 0.3 //false

Чтобы не вникать в детали и при этом не иметь проблем с вещественными числами вообще, нужно не превышать разрядность целочисленной части и не иметь дело с дробными (т.е. пользоваться, как целыми). И как только эти правила нарушены, гарантия исчезает - и могут появиться погрешности.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Seasle
@Seasle Куратор тега JavaScript
console.log(Number.MAX_SAFE_INTEGER < 9999999999999999); // true

Используйте BigInt
console.log(9999999999999999n); // 9999999999999999n
Ответ написан
Fragster
@Fragster
помогло? отметь решением!
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы