Секреты чисел в JS
Ошибки округления
В Javascript могут происходить интересные вещи, если вы не знаете, как он работает внутри. Например, числа с плавающей запятой вызывают некоторые ошибки округления. 0,1 и 0,2 не могут быть представлены точно. Следовательно, 0,1 + 0,2 === 0,3 дает ложь.
Итак, почему это происходит? Javascript использует 32-битную систему счисления с плавающей запятой. Для представления многих десятичных знаков в двоичном формате требуется бесконечное количество цифр. Попытка вычислить 0,1 (1/10) приводит к неопределенному количеству десятичных знаков. Результатом 0.1 + 0.2
является 0.30000000000000004
, что не равно 0.3
.
Номер.ЭПСИЛОН
Number.EPSILON
возвращает наименьший интервал между двумя представимыми числами. Это полезно для задачи с аппроксимацией с плавающей запятой.
function numberEquals(x: number, y: number) { return Math.abs(x — y) < Number.EPSILON; } numberEquals(0.1 + 0.2, 0.3); // true
Разница между 0.1 + 0.2
и 0.3
будет меньше Number.EPSILON
.
Двойные точки
Числа могут быть преобразованы в строки с фиксированным количеством десятичных знаков. Если вы будете вызывать функцию toFixed()
непосредственно для целого числа, вам нужно будет использовать нотацию с двойными точками, например: 5..toFixed(1) === ‘5.0’
. Почему вы должны это делать? Просто потому, что первая запись через точку предназначена для представления чисел с плавающей запятой: 0.77.toFixed(1) === ‘0.7’
Вы можете использовать функцию toFixed()
в предыдущем примере для сопоставления равенства (0.1 + 0.2).toFixed(1) === 0.3.toFixed(1)
Примечание. Примитивы в Javascript не являются объектами, но почему вы можете использовать
”string”.length
,0.77.toFixed(1)
? Ну, Javascript создает специальный объект-оболочку со значением для примитива, когда вы вызываете метод, и удаляет его после выполнения.
Минимумы, максимумы
Number
содержит интересные константы, которые представляют максимальные и минимальные целые числа и числа с плавающей запятой. В Javascript есть Infinity
и -Infinity
, но это не настоящие числа.
Number.MAX_SAFE_INTEGER
возвращает наибольшее целое число. Это равно 9007199254740991
И это выражение верно:
Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2; // true
Number.MAX_VALUE
возвращает наибольшее число с плавающей запятой. Это равно 1.7976931348623157e+308
. То же выражение для него:
Number.MAX_VALUE + 1.111 === Number.MAX_VALUE + 2.022; // true
Минимальные значения представлены Number.MIN_VALUE
как наименьшее число с плавающей запятой, равное 5e-324
, и Number.MIN_SAFE_INTEGER
, равное -9007199254740991
.Number.MIN_VALUE
также является ближайшим к нулю числом с плавающей запятой.
Number.MIN_VALUE — 1 === -1; // true
Почему это правда? Поскольку это выражение похоже на 0–1 === -1
Краткое содержание
Подытожим размер чисел Javascript:
-Infinity < Number.MIN_SAFE_INTEGER < Number.MIN_VALUE < 0 < Number.MAX_SAFE_INTEGER < Number.MAX_VALUE < Infinity
Когда вы работаете с числами с плавающей запятой, вы должны быть осторожны и учитывать ошибки округления, потому что некоторые числа не могут быть представлены точно. Вы можете использовать сторонние библиотеки или проверять различия между числами с помощью Number.EPSILON
.
Фото автора Волкан Олмез на Unsplash