Может ли кто-нибудь уточнить точность и переполнение чисел в JavaScript? - PullRequest
3 голосов
/ 24 мая 2019

Я смотрел на Number.isInteger() на MDN .Я наткнулся на этот пример -

Number.isInteger(5.000000000000001); // false

Я изменил значение на 5.0000000000000001, и если я выполню тот же метод на консоли, результат будет:

Number.isInteger(5.0000000000000001); // true

Также 5.0000000000000001 === 5 оказывается true.

Может кто-нибудь объяснить, что здесь происходит?

1 Ответ

3 голосов
/ 24 мая 2019

JavaScript использует базовый 64-битный двоичный формат IEEE-754 с плавающей запятой.В этом формате каждое конечное число выражается как целое число M , умноженное на степень 2, 2 E .Величина M должна быть меньше 2 53 , а E может составлять от -1074 до 971. (Более распространенное описание масштабов M и E по-разному, так что M имеет дробные биты, а не целое число, но это эквивалентно математически.)

Для числа 5.000000000000001, наиболееточно можно представить, как использовать E = −50, потому что это делает M настолько большим, насколько будет соответствовать, около 5 • 2 50 = 1,25 • 2 52 .Если бы мы сделали E на единицу меньше, M должно было бы быть около 1,25 • 2 53 , что превышает предел 2 53 .

Итак, учитывая E = −50, мы хотим 5.000000000000001 = M • 2 −50 , что означает M = 5.000000000000001 • 2 50 = 5 • 2 50 + .000000000000001 • 2 50 .Очевидно, первый член, 5 • 2 50 , является целым числом.Второй член, .000000000000001 • 2 50 , составляет около 1,1259.Таким образом, при преобразовании 5.000000000000001 в числовой формат JavaScript нам нужно сделать M целым числом, поэтому мы должны округлить 1.1259 до 1. В результате получим M = 5 • 2 50 + 1, поэтому число равно (5 • 2 50 + 1) • 2 −50 = 5.00000000000000088817841970012523233890533447265625.

С другой стороны, когдау нас есть 5.0000000000000001, с еще одним нулем, у нас есть 5.0000000000000001 • 2 50 = 5 • 2 50 + .0000000000000001 • 2 50 .В этом случае второе слагаемое .0000000000000001 • 2 50 составляет около 0,11259.Таким образом, при преобразовании 5.0000000000000001 в числовой формат JavaScript необходимо округлить .11259 до 0, поэтому число равно ((5 • 2 50 ) • 2 −50 = 5.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...