Это определяется языком? Есть ли определенный максимум? В разных браузерах он разный?
Какое наивысшее целочисленное значение JavaScript, к которому может перейти число без потери точности?
Ответы (21)
В JavaScript есть два числовых типа: Number
и _ 2_.
Наиболее часто используемый тип числа, Number
, представляет собой 64-битное число с плавающей запятой IEEE 754.
Наибольшее точное целое значение этого типа - Number.MAX_SAFE_INTEGER
< / a>, то есть:
- 2 53 -1, или
- +/- 9,007,199,254,740,991, or
- девять квадриллионов семь триллионов сто девяносто девять миллиардов двести пятьдесят четыре миллиона семьсот сорок тысяч девятьсот девяносто один
Для сравнения: один квадриллион байтов - это петабайт (или тысяча терабайт).
«Безопасный» в этом контексте относится к способности точно представлять целые числа и правильно их сравнивать.
Обратите внимание, что все положительные и отрицательные целые числа, величина которых не превышает 2 53, могут быть представлены в типе
Number
(действительно, целое число 0 имеет два представления, +0 и -0).
Чтобы безопасно использовать целые числа большего размера, вам необходимо использовать BigInt
, у которого нет верхней границы.
Обратите внимание, что побитовые операторы и операторы сдвига работают с 32-разрядными целыми числами, поэтому в этом случае максимальное безопасное целое число равно 2 31 -1 или 2 147 483 647.
const log = console.log
var x = 9007199254740992
var y = -x
log(x == x + 1) // true !
log(y == y - 1) // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:
log(x / 2) // 4503599627370496
log(x >> 1) // 0
log(x | 1) // 1
Техническое примечание по теме номера 9 007 199 254 740 992: существует точное представление этого значения в стандарте IEEE-754, и вы можете присвоить и прочитать это значение из переменной, поэтому для очень тщательно выбранных приложений в домене целых чисел, меньших или равных этому значению, можно рассматривать как максимальное значение.
В общем случае вы должны рассматривать это значение IEEE-754 как неточное, потому что неясно, кодирует ли оно логическое значение 9,007,199,254,740,992 или 9,007,199,254,740,993.
2^53
. Я отредактировал, чтобы сделать ответ более ясным
- person Jimmy; 15.10.2011
Number.MAX_VALUE - 1
не является допустимым значением.
- person Jimmy; 28.05.2013
Number.MAX_SAFE_INTEGER
(уже запущена в Chrome с включенным экспериментальным JS). Пока этот ответ хорош.
- person rvighne; 17.03.2014
x == x + 1
, что означает, что мы теряем точность.
- person Jimmy; 24.03.2016
>>>
определен на uint32_t
, а не на int32_t
.
- person tsh; 11.07.2017
›= ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
‹= ES5
Из справки:
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
Number.MIN_VALUE
- это наименьшее возможное положительное число. наименьшее значение (т.е. меньше всего остального), вероятно, -Number.MAX_VALUE
.
- person Michael Scheper; 11.06.2014
Number.MAX_VALUE
является целым числом, вы не можете пройти мимо 2^53
без потери точности.
- person Teepeemm; 23.07.2014
Number.MIN_SAFE_INTEGER
и Number.MAX_SAFE_INTEGER
- person superlukas; 31.08.2014
Это 2 53 == 9 007 199 254 740 992. Это связано с тем, что Number
s хранятся как числа с плавающей запятой в 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) {
// infinite loop
}
Дополнительная литература: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
i += 1000000000
- person ninjagecko; 08.07.2015
В JavaScript есть число Infinity
.
Примеры:
(Infinity>100)
=> true
// Also worth noting
Infinity - 1 == Infinity
=> true
Math.pow(2,1024) === Infinity
=> true
Этого может быть достаточно для некоторых вопросов по этой теме.
min
, когда вы ищете минимальное значение.
- person djjeck; 24.10.2012
Infinity - 1 === Infinity
- person H.Wolper; 18.10.2013
Infinity - 1 + 1
.
- person Andrew; 11.06.2020
Ответ Джимми правильно представляет непрерывный целочисленный спектр JavaScript от -9007199254740992 до 9007199254740992 strong> инклюзивный (извините 9007199254740993, вы можете подумать, что вы 9007199254740993, но вы ошибаетесь! Демонстрация ниже или в jsfiddle).
console.log(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);
x++
дает вам значение x до того, как произошло приращение, так что, вероятно, это объясняет несоответствие. Если вы хотите, чтобы выражение оценивалось так же, как окончательное значение x, вы должны изменить его на ++x
.
- person peterflynn; 24.11.2013
"last number where +1 works" == "max number w/out losing precision" - 1
- person Briguy37; 25.11.2013
Чтобы быть в безопасности
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))
Эти ограничения налагаются внутренним представлением типа «Число», которое обычно соответствует представлению с плавающей запятой двойной точности IEEE 754. (Обратите внимание, что в отличие от типичных целых чисел со знаком, величина отрицательного предела такая же, как величина положительного предела, из-за характеристик внутреннего представления, которое фактически включает отрицательный 0!)
ECMAScript 6:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
MAX_SAFE_INTEGER
во всех браузерах, работая в обратном направлении? Стоит ли вместо этого двигаться вперед? То есть Number.MAX_SAFE_INTEGER = 2 * (Math.pow (2, 52) - 1) + 1;
- person kjv; 26.05.2015
Math.pow(2, 53)-1
безопасная операция? Оно на единицу больше наибольшего безопасного целого числа.
- person ioquatix; 13.03.2017
Math.pow(2, 53)
точно представимо, а вычитание четко определено и точно.
- person Daira Hopwood; 17.10.2020
Многие предыдущие ответы показали, что 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:
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
Слева от стрелки у нас есть битовое значение 1 и смежная точка счисления. При использовании экспоненты слева точка системы счисления перемещается на 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)
1 . 0000 ---- 0000 * 2^52 * 2 => 1 0000 ---- 0000. * 2
|-- 52 bits --| |-- 52 bits --|
(By consuming the 2^52, radix
point has no way to go, but
there is still one 2 left in
exponent part)
=> 1 . 0000 ---- 0000 * 2^53
|-- 52 bits --|
Теперь мы получаем 9,007,199,254,740,992, и для числа, большего, чем это, формат может обрабатывать только приращения 2, потому что каждое приращение 1 в дробной части в конечном итоге умножается на левая 2 в показательной части. Вот почему 64-битный двоичный формат двойной точности не может содержать нечетные числа, если число больше 9,007,199,254,740,992:
(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 --|
Значение 0,1 в двоичном формате равно 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
/**
Please note that if you try this yourself and, say, log
these numbers to the console, they will get rounded. JavaScript
rounds if the number of digits exceed 17. The value
is internally 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 бит.
Из Википедии (подробнее см. Здесь)
Таким образом, чтобы показатель степени был равен 2 ^ 52, нам точно нужно установить e = 1075.
Другой, возможно, уже дал общий ответ, но я подумал, что было бы неплохо дать быстрый способ его определения:
for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);
Это дает мне 9007199254740992 менее чем за миллисекунду в Chrome 30.
Он проверит степень двойки, чтобы определить, какая из них при «добавлении» 1 равна ему.
Все, что вы хотите использовать для побитовых операций, должно находиться в диапазоне от 0x80000000 (-2147483648 или -2 ^ 31) до 0x7fffffff (2147483647 или 2 ^ 31-1).
Консоль сообщит вам, что 0x80000000 равно +2147483648, а 0x80000000 и 0x80000000 равно -2147483648.
Пытаться:
maxInt = -1 >>> 1
В Firefox 3.6 это 2 ^ 31-1.
^
означает возведен во власть. В консоли javascript ^
является XOR, а не возведен в
- person kumarharsh; 24.12.2013
101
, а 2 - это 010
. Теперь, если вы выполните побитовое XOR, вы получите 5(101) ^ 2(010) = 7(111)
ПРОЧИТАЙТЕ ЭТО, ЕСЛИ ВЫ ЗАБОТАЕТЕ Здесь обсуждается Math.pow()
, а не ^
оператор
- person kumarharsh; 25.12.2013
На момент написания JavaScript получает новый тип данных: BigInt
. Это предложение TC39 на этапе 4, которое должно быть включено в EcmaScript 2020. BigInt
доступен в Chrome 67+, FireFox 68+, Opera 54 и Node 10.4.0. Он реализуется в Safari и др ... Он вводит числовые литералы с суффиксом «n» и допускает произвольную точность:
var a = 123456789012345678901012345678901n;
Конечно, точность все равно будет потеряна, когда такое число (возможно, непреднамеренно) приведено к числовому типу данных.
И, очевидно, всегда будут ограничения точности из-за ограниченного объема памяти и затрат времени на выделение необходимой памяти и выполнение арифметических действий с такими большими числами.
Например, генерация числа из ста тысяч десятичных цифр займет заметную задержку до завершения:
console.log(BigInt("1".padEnd(100000,"0")) + 1n)
... но это работает.
Я провел простой тест с формулой X- (X + 1) = - 1, и наибольшее значение X, которое я могу получить для работы в Safari, Opera и Firefox (проверено на OS X), составляет 9e15. Вот код, который я использовал для тестирования:
javascript: alert(9e15-(9e15+1));
9000000000000000
есть 1 значащая цифра. в `9007199254740992` 15 значащих цифр.
- person Royi Namir; 13.11.2013
9000000000000000
как есть - есть 1
SF. где 90*10^14
имеет 2. (sigfigscalculator.appspot.com) & mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (нижний раздел)
- person Royi Namir; 13.11.2013
Я пишу это так:
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;
Перейдем к источникам
Описание
Константа
MAX_SAFE_INTEGER
имеет значение9007199254740991
(9,007,199,254,740,991 или ~ 9 квадриллионов). Причина этого числа заключается в том, что JavaScript использует числа в формате с плавающей запятой двойной точности как указано в IEEE 754 и может безопасно представлять только числа от-(2^53 - 1)
до2^53 - 1
.Под безопасностью в этом контексте понимается способность точно представлять целые числа и правильно их сравнивать. Например,
Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2
будет оцениваться как истина, что математически неверно. См. Number.isSafeInteger () для дополнительной информации.Поскольку
MAX_SAFE_INTEGER
является статическим свойством Number , вы всегда используете его какNumber.MAX_SAFE_INTEGER
, а не как свойство Номер созданного вами объекта.
Совместимость с браузером
В JavaScript числа представлены как 2^53 - 1
.
Однако вычисляются Bitwise operation
на 32 bits ( 4 bytes )
, что означает, что если вы превысите 32-битную смену, вы начнете терять биты.
Во встроенном javascript Google Chrome вы можете перейти примерно к 2 ^ 1024, прежде чем число будет называться бесконечным.
Скато пишет:
все, что вы хотите использовать для побитовых операций, должно находиться в диапазоне от 0x80000000 (-2147483648 или -2 ^ 31) до 0x7fffffff (2147483647 или 2 ^ 31-1).
консоль сообщит вам, что 0x80000000 равно +2147483648, но 0x80000000 и 0x80000000 равно -2147483648
Шестнадцатеричные десятичные числа - это положительные значения без знака, поэтому 0x80000000 = 2147483648 - это математически правильно. Если вы хотите сделать это значение со знаком, вам нужно сдвинуть вправо: 0x80000000 >> 0 = -2147483648. Вы также можете написать 1 ‹---------------- 31.
Firefox 3, похоже, не имеет проблем с огромными числами.
1e + 200 * 1e + 100 рассчитывается как 1e + 300.
У Safari, похоже, тоже нет проблем с этим. (Для записи, это на Mac, если кто-то еще решит это проверить.)
Если только я не потерял мозг в это время суток, это намного больше, чем 64-битное целое число.
100000000000000010 - 1 => 100000000000000020
- person Ryan; 08.10.2011
Node.js и Google Chrome, похоже, используют 1024-битные значения с плавающей запятой, поэтому:
Number.MAX_VALUE = 1.7976931348623157e+308
2^53
обозначается как MAX_SAFE_INT
, потому что выше этой точки значения становятся приблизительными, так же как и дроби.
- person IMSoP; 16.06.2014
1n << 10000n
- это действительно очень большое целое число, без потери точности, без каких-либо зависимостей (и, разумеется, даже близко не к пределу). - person Amadan   schedule 06.01.20201n << 10000n
? - person Dmitri Zaitsev   schedule 08.01.2020n
.BigInt
класс является частью проекта спецификации ES2020, уже реализованного в большинстве браузеров; вы можете попытаться оценить это, например, Chrome или Firefox, без внешних библиотек, и получить 3011-значныйBigInt
. - person Amadan   schedule 08.01.2020.1+.2
? - person Dmitri Zaitsev   schedule 08.01.2020