Каково самое высокое целочисленное значение JavaScript, на которое может перейти число без потери точности?
это определяется языком? Существует ли определенный максимум? Отличается ли это в разных браузерах?
21 ответов
+/- 9007199254740991
обратите внимание, что все положительные и отрицательные целые числа, величина которых не превышает 253 представимы в виде числа (по сути, целое число 0 имеет два представления +0 и -0).
Это 64-разрядные значения с плавающей запятой, наибольшее точное интегральное значение-253-1 или 9007199254740991
. В ES6 это определяется как количество.MAX_SAFE_INTEGER.
обратите внимание, что побитовые операторы и операторы сдвига работают на 32-битных интах, поэтому в этом случае максимальное безопасное целое число равно 231-1, или 2147483647.
Проверьте это!
var x = 9007199254740992;
var y = -x;
x == x + 1; // true !
y == y - 1; // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:
x / 2; // 4503599627370496
x >> 1; // 0
x | 1; // 1
техническое примечание по вопросу числа 9007199254740992: существует точное представление IEEE-754 этого значения, и вы можете назначить и прочитать это значение из переменной, поэтому для внимательно выбранные приложения в области целых чисел, меньших или равных этому значению, можно рассматривать как максимальное значение.
В общем случае вы должны рассматривать это значение IEEE-754 как неточное, потому что неясно, кодирует ли оно логическое значение 9007199254740992 или 9007199254740993.
> = ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
С ссылка:
Number.MAX_VALUE;
Number.MIN_VALUE;
console.log('MIN_VALUE', Number.MIN_VALUE);
console.log('MAX_VALUE', Number.MAX_VALUE);
console.log('MIN_SAFE_INTEGER', Number.MIN_SAFE_INTEGER); //ES6
console.log('MAX_SAFE_INTEGER', Number.MAX_SAFE_INTEGER); //ES6
в 253 == 9 007 199 254 740 992. Это потому что Number
s хранятся как с плавающей запятой в 52-битной мантиссе.
минимальное значение -253.
Это делает некоторые забавные вещи происходят
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) {
// infinite loop
}
дальнейшее чтение: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
в JavaScript есть число под названием Infinity
.
примеры:
(Infinity>100)
=> true
// Also worth noting
Infinity - 1 == Infinity
=> true
Math.pow(2,1024) === Infinity
=> true
этого может быть достаточно для некоторых вопросов, касающихся этой темы.
Джимми правильно представляет непрерывный целочисленный спектр JavaScript как -9007199254740992 to 9007199254740992 включительно (извините 9007199254740993, вы можете подумать, что вы 9007199254740993, но вы ошибаетесь! демонстрация ниже или в jsfiddle).
document.write(9007199254740993);
однако нет ответа, который находит / доказывает это программно (кроме одного CoolAJ86 говорится в ответ это закончится через 28.56 лет ;), так что вот немного более эффективный способ сделать это (если быть точным, это более эффективно примерно на 28.559999999968312 лет :), наряду с тест скрипку:
/**
* Checks if adding/subtracting one to/from a number yields the correct result.
*
* @param number The number to test
* @return true if you can add/subtract 1, false otherwise.
*/
var canAddSubtractOneFromNumber = function(number) {
var numMinusOne = number - 1;
var numPlusOne = number + 1;
return ((number - numMinusOne) === 1) && ((number - numPlusOne) === -1);
}
//Find the highest number
var highestNumber = 3; //Start with an integer 1 or higher
//Get a number higher than the valid integer range
while (canAddSubtractOneFromNumber(highestNumber)) {
highestNumber *= 2;
}
//Find the lowest number you can't add/subtract 1 from
var numToSubtract = highestNumber / 4;
while (numToSubtract >= 1) {
while (!canAddSubtractOneFromNumber(highestNumber - numToSubtract)) {
highestNumber = highestNumber - numToSubtract;
}
numToSubtract /= 2;
}
//And there was much rejoicing. Yay.
console.log('HighestNumber = ' + highestNumber);
чтобы быть в безопасности
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);
}());
ECMAScript 6:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
короткий ответ: "это зависит."
Если вы используете побитовые операторы в любом месте (или если вы ссылаетесь на длину массива), диапазоны:
без знака:0…(-1>>>0)
подпись: (-(-1>>>1)-1)…(-1>>>1)
(случается так, что побитовые операторы и максимальная длина массива ограничены 32-битными целыми числами.)
Если вы не используете побитовые операторы или не работаете с длинами массивов:
подпись: (-Math.pow(2,53))…(+Math.pow(2,53))
эти ограничения налагаются внутренним представлением типа "число", которое обычно соответствует представлению с плавающей запятой двойной точности IEEE 754. (Обратите внимание, что в отличие от типичных целых чисел со знаком, величина отрицательного предела такая же, как и величина положительного предела, из-за характеристик внутреннего представления, которое фактически включает a отрицательный 0!)
другие, возможно, уже дали общий ответ, но я подумал, что было бы неплохо дать быстрый способ его определения:
for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);
что дает мне 9007199254740992 менее чем за миллисекунду в Chrome 30.
он будет проверять силы 2, чтобы найти, какой из них, когда "добавлен" 1, равен себе.
все, что вы хотите использовать для побитовых операций, должно находиться между 0x80000000 (-2147483648 или -2^31) и 0x7fffffff (2147483647 или 2^31 - 1).
консоль скажет вам, что 0x80000000 равно +2147483648, но 0x80000000 & 0x80000000 равно -2147483648.
многие ответы ранее показывают результат true
of 9007199254740992 === 9007199254740992 + 1
сказать, что 9 007 199 254 740 991 - максимальное безопасное целое число.
что делать, если мы продолжаем делать накопление:
input: 9007199254740992 + 1 output: 9007199254740992 // expected: 9007199254740993
input: 9007199254740992 + 2 output: 9007199254740994 // expected: 9007199254740994
input: 9007199254740992 + 3 output: 9007199254740996 // expected: 9007199254740995
input: 9007199254740992 + 4 output: 9007199254740996 // expected: 9007199254740996
мы могли бы узнать, среди чисел больше, чем 9 007 199 254 740 992, только четные числа представимое.
это запись, чтобы объяснить, как двойной точности 64-битный двоичный формат работать над этим. Давайте посмотрим, как 9 007 199 254 740 992 пройдет (представлено), используя этот двоичный формат.
начнем с 4 503 599 627 370 496 с краткой версией формата first:
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
на левой стороне стрелки, у нас есть значение бита 1, и прилегающей точки радикса, затем путем умножения 2^52
, мы вправо перемещаем точку радикса 52 шагов, и он идет до конца. Сейчас мы вам 4503599627370496 в двоичном.
теперь мы начинаем накапливать 1 к этому значению, пока все биты установлены на 1, что равно 9 007 199 254 740 991 в десятичное.
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
(+1)
1 . 0000 ---- 0001 * 2^52 => 1 0000 ---- 0001.
(+1)
1 . 0000 ---- 0010 * 2^52 => 1 0000 ---- 0010.
(+1)
.
.
.
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
, потому что двойной точности 64-разрядный двоичный формат, он строго сплавляет 52 бита для фракции, больше бит не доступен для переноса для добавления еще одного 1, поэтому мы могли бы установить все биты обратно до 0 и манипулировать экспоненциальной частью:
|--> This bit is implicit and persistent.
|
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
|-- 52 bits --| |-- 52 bits --|
(+1)
(radix point have no way to go)
1 . 0000 ---- 0000 * 2^52 * 2 => 1 0000 ---- 0000. * 2
|-- 52 bits --| |-- 52 bits --|
=> 1 . 0000 ---- 0000 * 2^53
|-- 52 bits --|
теперь мы получаем 9 007 199 254 740 992, и с числом больше, чем это, то, что формат может содержать 2 раза дроби:
(consume 2^52 to move radix point to the end)
1 . 0000 ---- 0001 * 2^53 => 1 0000 ---- 0001. * 2
|-- 52 bits --| |-- 52 bits --|
так что, когда номер узнать больше 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, только 4 раза фракции можно провести:
input: 18014398509481984 + 1 output: 18014398509481984 // expected: 18014398509481985
input: 18014398509481984 + 2 output: 18014398509481984 // expected: 18014398509481986
input: 18014398509481984 + 3 output: 18014398509481984 // expected: 18014398509481987
input: 18014398509481984 + 4 output: 18014398509481988 // expected: 18014398509481988
как насчет числа между [ 2 251 799 813 685 248, 4 503 599 627 370 496 )?
1 . 0000 ---- 0001 * 2^51 => 1 0000 ---- 000.1
|-- 52 bits --| |-- 52 bits --|
битовое значение 1 после точки radix равно 2^-1 точно. (=1/2, =0,5) Поэтому, когда число меньше 4 503 599 627 370 496 (2^52), есть один бит, доступный для представления 1/2 раза в число:
input: 4503599627370495.5 output: 4503599627370495.5
input: 4503599627370495.75 output: 4503599627370495.5
меньше 2 251 799 813 685 248 (2^51)
input: 2251799813685246.75 output: 2251799813685246.8 // expected: 2251799813685246.75
input: 2251799813685246.25 output: 2251799813685246.2 // expected: 2251799813685246.25
input: 2251799813685246.5 output: 2251799813685246.5
// If the digits exceed 17, JavaScript round it to print it.
//, but the value is held correctly:
input: 2251799813685246.25.toString(2)
output: "111111111111111111111111111111111111111111111111110.01"
input: 2251799813685246.75.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
input: 2251799813685246.78.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
и каков доступный диапазон экспонента часть? формат выделяет для него 11 бит. Полный формат из Wiki: (для получения более подробной информации, пожалуйста, перейдите туда)
поэтому, чтобы получить 2^52 в экспоненциальной части, нам точно нужно установить e = 1075.
Я сделал простой тест с формулой X - (X+1)=-1, и наибольшее значение X, которое я могу получить для работы в Safari, Opera и Firefox (протестировано на OS X), - 9e15. Вот код, который я использовал для тестирования:
javascript: alert(9e15-(9e15+1));
Я пишу так:
var max_int = 0x20000000000000;
var min_int = -0x20000000000000;
(max_int + 1) === 0x20000000000000; //true
(max_int - 1) < 0x20000000000000; //true
же для int32
var max_int32 = 0x80000000;
var min_int32 = -0x80000000;
в Google Chrome встроенный javascript, вы можете перейти к приблизительно 2^1024, прежде чем число называется бесконечность.
со счето wrotes:
все, что вы хотите использовать для побитовых операций должны быть между 0x80000000 (-2147483648 или -2^31) и 0x7fffffff (2147483647 или 2^31 - 1).
консоль скажет вам, что 0x80000000 равно +2147483648, но Значение 0x80000000 & значение 0x80000000 равно -2147483648
шестнадцатеричные - это положительные значения без знака, поэтому 0x80000000 = 2147483648-это математически правильно. Если вы хотите сделать его подписанным значением, вы нужно сдвинуть вправо: 0x80000000 >> 0 = -2147483648. Вместо этого вы также можете написать 1
количество.Массив представляет максимальное числовое значение, представимое в JavaScript.
поскольку никто, кажется, не сказал этого, в v8 двигатель существует разница в поведении для 31 bits
номер и номер выше.
если у вас 32 bits
вы можете использовать первый бит, чтобы сообщить движку javascript, какой тип данных, а остальные биты содержат фактические данные. Вот что!--11-->V8 совсем как маленький оптимизация для 31 bis
numbers
(или раньше, Мои источники довольно устарели). У вас есть последний 31 bits
будучи числовым значением, а затем первым битом, сообщающим движку, является ли это число или ссылка на объект.
однако, если вы используете номер выше 31 bits
тогда данные не будут вписываться, номер будет упакован в 64-битный двойной, и оптимизации не будет.
нижняя строка в видео ниже:
предпочитаю числовые значения, которые могут быть представленным как 31bits подпись целое число.
В основном javascript не поддерживает долго.
поэтому для нормальных значений, которые он может представлять менее 32 бит, он будет использовать контейнер типа int. для целых значений, больших 32 бит, используется double. В двойном represntation целую часть составляет 53 бита, а остальное-мантисса( держать с плавающей точкой информации).
таким образом, вы можете использовать 2^53 - 1
стоимость которого составляет 9007199254740991
вы можете получить доступ к значению для использования в коде Number.MAX_SAFE_INTEGER
поехали в источник
описание
на
MAX_SAFE_INTEGER
константа имеет значение9007199254740991
(9,007,199,254,740,991 или ~9 квадриллионов). Причина этого числа заключается в том, что JavaScript использует номера формата с плавающей запятой двойной точности как указано в IEEE 754 и может безопасно представлять только числа между-(253 - 1)
и253 - 1
.Safe в этом контексте относится к возможность точно представлять целые числа и корректно их сравнивать. Например,
Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2
будет оцениваться как true, что математически неверно. См.количество.isSafeInteger () для получения дополнительной информации., потому что
MAX_SAFE_INTEGER
является статическим свойством , вы всегда используете его какNumber.MAX_SAFE_INTEGER
, а не как свойство объект, который вы создали.
браузер совместимость
Firefox 3, похоже, не имеет проблем с огромными числами.
1e + 200 * 1e + 100 рассчитает штраф до 1e + 300.
Safari, похоже, не имеет никаких проблем с этим. (Для записи, это на Mac, Если кто-то еще решит проверить это.)
Если я потерял мой мозг в это время дня, это намного больше, чем 64-битное целое.
узел.js и Google Chrome, похоже, используют значения с плавающей запятой 1024 бит, поэтому:
Number.MAX_VALUE = 1.7976931348623157e+308