Какое наибольшее целочисленное значение в JavaScript, при котором не теряется точность?
Определено ли это языком? Существует ли установленный максимум? Различается ли это в разных браузерах?
5 ответ(ов)
В JavaScript значение 2^53
равно 9 007 199 254 740 992
. Это связано с тем, что числа хранятся в формате с плавающей точкой, где используется 52-битная мантисса.
Минимальное значение равно -2^53
.
Из-за этого возникают некоторые интересные вещи:
Math.pow(2, 53) == Math.pow(2, 53) + 1
// >> true
А также это может быть опасно 😃
var MAX_INT = Math.pow(2, 53); // 9 007 199 254 740 992
for (var i = MAX_INT; i < MAX_INT + 2; ++i) {
// бесконечный цикл
}
В данном случае, при достижении значения MAX_INT
, добавление 1 к MAX_INT
не изменяет его, что приводит к бесконечному циклу. Будьте осторожны с большими числами в JavaScript!
В JavaScript существует специальное число, называемое Infinity
(бесконечность). Оно используется для представления числового значения, которое превышает любые конечные числа.
Вот несколько примеров:
(Infinity > 100)
// => true, так как бесконечность больше любого фиксированного числа, включая 100.
Infinity - 1 === Infinity
// => true, потому что вычитание конечного числа из бесконечности не изменяет её.
Math.pow(2, 1024) === Infinity
// => true, поскольку результат возведения 2 в степень 1024 превышает максимально допустимое число в JavaScript, что приводит к значению Infinity.
Эти примеры должны помочь в понимании работы с Infinity
и ответить на многие вопросы по этой теме.
Для безопасности
var MAX_INT = 4294967295;
Обоснование
Я решил проявить смекалку и найти значение, при котором x + 1 === x
, используя более прагматичный подход.
На моем компьютере скорость подсчета составляет около 10 миллионов операций в секунду... так что я сообщу окончательный ответ через 28,56 лет.
Если вы не готовы ждать так долго, могу поспорить, что:
- Большинство ваших циклов не выполняются 28,56 лет
9007199254740992 === Math.pow(2, 53) + 1
является достаточно убедительным доказательством- Вам следует придерживаться
4294967295
, что равноMath.pow(2, 32) - 1
, чтобы избежать ожидаемых проблем с битовыми сдвигами
Нахождение x + 1 === x
:
(function () {
"use strict";
var x = 0
, start = new Date().valueOf()
;
while (x + 1 != x) {
if (!(x % 10000000)) {
console.log(x);
}
x += 1
}
console.log(x, new Date().valueOf() - start);
}());
Краткий ответ: "это зависит."
Если вы используете побитовые операторы (или если речь идет о длине массива), диапазоны следующие:
Без знака: 0…(-1>>>0)
Со знаком: (-(-1>>>1)-1)…(-1>>>1)
Дело в том, что побитовые операторы и максимальная длина массива ограничены 32-битными целыми числами.
Если вы не используете побитовые операторы и не работаете с длиной массивов:
Со знаком: (-Math.pow(2,53))…(+Math.pow(2,53))
Эти ограничения накладываются внутренним представлением типа "Number", которое в общем случае соответствует представлению чисел с плавающей запятой двойной точности по стандарту IEEE 754. (Обратите внимание, что в отличие от типичных знаковых целых чисел, модуль отрицательного предела равен модулю положительного предела из-за особенностей внутреннего представления, которое на самом деле включает в себя отрицательный 0!)
В ECMAScript 6 значение Number.MAX_SAFE_INTEGER
равно (2^{53} - 1), что представляет собой максимальное безопасное целое число, которое можно использовать в JavaScript без потери точности. Соответственно, Number.MIN_SAFE_INTEGER
устанавливается как отрицательная версия этого значения, т.е. (-Number.MAX_SAFE_INTEGER).
Вот корректный код для определения этих констант:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; // 9007199254740991
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER; // -9007199254740991
Эти значения определяют диапазон безопасных целых чисел, которые JavaScript может точно представлять. Если число выходит за этот диапазон, могут возникнуть ошибки с точностью при вычислениях.
Как определить, виден ли элемент DOM в текущей области просмотра?
Как выполнить целочисленное деление и отдельно получить остаток в JavaScript?
В чем разница между String.slice и String.substring?
Существует ли ссылка на "последнюю" библиотеку jQuery в Google APIs?
Как создать диалог с кнопками "Ок" и "Отмена"