Какое наивысшее целочисленное значение JavaScript, к которому может перейти число без потери точности?

Это определяется языком? Есть ли определенный максимум? В разных браузерах он разный?


person TALlama    schedule 20.11.2008    source источник
comment
Вам не нужно зависеть от ограничений JS с такими библиотеками, как github.com/MikeMcl/big.js, см., например, здесь для тестов надежности   -  person Dmitri Zaitsev    schedule 18.05.2016
comment
какое наибольшее целое значение можно использовать с big.js?   -  person George    schedule 26.03.2018
comment
@George Вот API big.js: mikemcl.github.io/big.js/#dp   -  person simhumileco    schedule 18.07.2018
comment
Вопрос не имеет смысла. Что означает переход числа к целочисленному значению? Если вы просто хотите спросить, какое наибольшее целое число вы можете представить в JS, самое высокое (конечное) число само по себе является целым числом.   -  person Veky    schedule 26.10.2018
comment
@DmitriZaitsev Нам больше не нужно зависеть от внешних библиотек (по крайней мере, в некоторых браузерах). 1n << 10000n - это действительно очень большое целое число, без потери точности, без каких-либо зависимостей (и, разумеется, даже близко не к пределу).   -  person Amadan    schedule 06.01.2020
comment
@Amadan Откуда здесь 1n << 10000n?   -  person Dmitri Zaitsev    schedule 08.01.2020
comment
@DmitriZaitsev Просто случайный пример большого числа.   -  person Amadan    schedule 08.01.2020
comment
@Amadan Так как это случайное число может устранить необходимость во внешних библиотеках?   -  person Dmitri Zaitsev    schedule 08.01.2020
comment
@DmitriZaitsev Обратите внимание на суффикс n. BigInt класс является частью проекта спецификации ES2020, уже реализованного в большинстве браузеров; вы можете попытаться оценить это, например, Chrome или Firefox, без внешних библиотек, и получить 3011-значный BigInt.   -  person Amadan    schedule 08.01.2020
comment
@Amadan Это только для целых чисел. Например. как точно добавить .1+.2?   -  person Dmitri Zaitsev    schedule 08.01.2020
comment
@DmitriZaitsev: Да, это только для целых чисел. Это вопрос о целых числах.   -  person Amadan    schedule 08.01.2020


Ответы (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.

person Jimmy    schedule 20.11.2008
comment
Это кажется правильным, но есть ли где-нибудь это определение, например MAX_INT в языке C или Integer.MAX_VALUE в Java? - person TALlama; 21.11.2008
comment
согласно стандарту IEEE_754, 64-битная с плавающей запятой использует 53 бита для мантиссы. Что касается константы javascript, мне ничего не известно. - person Jimmy; 21.11.2008
comment
Итак, какое наименьшее и наибольшее целое число мы можем использовать для обеспечения точной точности? - person Pacerier; 15.10.2011
comment
для простых операций в первой части моего ответа указано 2^53. Я отредактировал, чтобы сделать ответ более ясным - person Jimmy; 15.10.2011
comment
Возможно, стоит отметить, что в javascript нет фактического (int). Каждый экземпляр Number равен (float) или NaN. - person Beetroot-Beetroot; 31.08.2012
comment
@ Свекла-Свекла или +/- Бесконечность - person skeggse; 01.12.2012
comment
@ LucioM.Tato Вопрос специально запрашивает без потери точности Number.MAX_VALUE - наибольшее значение, точка, но, например, Number.MAX_VALUE - 1 не является допустимым значением. - person Jimmy; 28.05.2013
comment
Каждый экземпляр Number - это (float) ‹stop here› или NaN. ... Или +/- Infinity: избыточный, IEEE-754 (float) кодирует NaN и +/- Infinity как часть формата. Также -0 - person MickLH; 26.11.2013
comment
@TALlama В ES6 для этого будет константа: Number.MAX_SAFE_INTEGER (уже запущена в Chrome с включенным экспериментальным JS). Пока этот ответ хорош. - person rvighne; 17.03.2014
comment
9007199254740992 на самом деле не является максимальным значением, последний бит здесь уже предполагается равным нулю, и поэтому вы потеряли 1 бит точности. Настоящий номер сейфа - 9007199254740991 (Number.MAX_SAFE_INTEGER). - person Willem D'Haeseleer; 21.08.2014
comment
Между прочим, это число читается как: девять квадриллионов, семь триллионов, сто девяносто девять миллиардов, двести пятьдесят четыре миллиона, семьсот сорок тысяч, девятьсот девяносто один. - person K Lee; 13.03.2015
comment
Кто-нибудь, объясните мне одну вещь. Свойство MAX_VALUE имеет значение приблизительно 1.79E + 308 (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/). 1.79E + 308 - очень большое число, которое намного больше 2 ^ 53. Что означает Number.MAX_VALUE? - person Evgeni Nabokov; 24.03.2016
comment
@EvgeniNabokov: Number.MAX_VALUE - это наибольшее значение, представленное 64-битным числом с плавающей запятой. Однако 64-битное число с плавающей запятой не может представлять все целые числа меньше 1.79E + 308 (как вы, вероятно, знаете, 64-битные могут представлять только 2 ^ 64 = 1.84E + 19 уникальных значений). Number.MAX_SAFE_VALUE или 9007199254740991 имеет свойство, заключающееся в том, что каждое положительное целое число ‹= 9007199254740991 точно может быть представлено 64-битным числом с плавающей запятой без потери точности. В моем фрагменте кода в ответе вы можете видеть, что для значений x, превышающих 9007199254740991, вы можете иметь x == x + 1, что означает, что мы теряем точность. - person Jimmy; 24.03.2016
comment
+1 за указание ограничений побитовых операторов !! Это полностью ускользает от меня, почему они решили использовать там 32-битную версию, поскольку она, очевидно, использует 64 для Number. - person Ciprian Tomoiagă; 10.03.2017
comment
Итак, в миллисекундах UNIX это будет 12 октября 287396 года. - person Kyle Delaney; 27.06.2017
comment
особый случай: >>> определен на uint32_t, а не на int32_t. - person tsh; 11.07.2017
comment
@CiprianTomoiaga: Потому что 80386 был 32-битным процессором и не мог выполнять эти операции на 64-битном. А 80387 не имеет сменных операций. Пожалуйста, помните, что JS немного появился ... - person Bodo Thiesen; 24.08.2017
comment
@BodoThiesen: Было ли когда-нибудь время, когда расширение побитовых операторов до 53 бит имело какое-либо значимое отрицательное влияние на производительность Javascript? В первые дни Javascript, когда 32-битные ЦП были главенствующими, производительность больше зависела от скорости интерпретатора и символьного поиска, чем от чего-либо, связанного с реальными числовыми операциями. - person supercat; 12.06.2018
comment
Почему он 53-битный, если в документе говорится, что для хранения дроби 52 бита? Думаю, стоит упомянуть причину этого (по крайней мере, у меня не хватило ума понять это самому), эта статья объясняет это рядом с разделом Примеры хранения целых чисел. - person Marty ZHANG; 21.06.2018
comment
@supercat, я не сказал, я считаю, что это была хорошая причина, я просто сказал, я верю, это была причина. И люди иногда стремятся оптимизировать не в тех местах. В любом случае: выполнение сдвига для двойного значения создает необходимость либо преобразовать его в целое число и обратно, либо сильно округлить до и после сдвига. И да: выполнение 64-битного сдвига будет всего на одну инструкцию больше, чем выполнение 32-битного сдвига. - person Bodo Thiesen; 06.07.2018
comment
@ T.J.Crowder - это просто другое определение потери точности, и я думаю, что его использовать в качестве общего принципа более небезопасно. Представление IEEE-754 для значения 9007199254740992 совпадает с представлением для значения 9007199254740993, поэтому, если у вас когда-либо был этот битовый шаблон, вы должны рассматривать его как неточное значение, поскольку вы не можете быть уверены, какое из двух значений оно средства. - person Jimmy; 29.09.2018
comment
@ Джимми - Это все немного произвольно. :-) Но мне нравятся ваши рассуждения, хотя я спорю с Представление IEEE-754 для значения 9007199254740992 такое же, как представление для значения 9007199254740993 ... Нет никакого представления для 9007199254740993, вообще. Дело не в том, что это то же самое, что и 9007199254740992; нет ни одного. Поэтому все, что пытается использовать это значение, должно снизиться до 9007199254740992 или до 9007199254740994. (продолжение) - person T.J. Crowder; 29.09.2018
comment
(продолжение) Но отдельно, в поддержку вашего определения: 9007199254740991 - это последнее значение, для которого есть бит для места 1; начиная с 9007199254740992 младший бит - это 2 место. Таким образом, потеря точности. Так что да, можно по-разному смотреть на это, но мне нравится ваша точка зрения. :-) Может быть, сложить часть этого в ответ? Поскольку 9007199254740992 проводится точно ... - person T.J. Crowder; 29.09.2018
comment
Спасибо за примечание о побитовых операторах и операторах сдвига, работающих с 32-битными целыми числами. Только что заметил: 1073741824 * 2 - это 2147483648, но 1073741824 ‹---------------- 1 - это -2147483648 - person Galaxy; 09.09.2019
comment
Как рассчитать максимальное число с учетом определенного количества десятичных знаков? - person Dominic; 16.10.2020
comment
@Dominic Не существует такого количества десятичных знаков X ›0, чтобы можно было представить все десятичные числа с такой точностью. например, десятичное число 0,1 не имеет точного представления в двоичном формате и не может быть точно представлено числами с плавающей запятой. - person Jimmy; 17.10.2020

›= 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

person Peter Bailey    schedule 20.11.2008
comment
Я отредактировал вопрос, чтобы он был немного более точным в отношении максимальных значений Integer, а не только максимального значения Number. Извините за путаницу, здесь. - person TALlama; 21.11.2008
comment
Гарантированно ли возвращаемый результат будет одинаковым во всех браузерах? - person Pacerier; 21.09.2013
comment
Обратите внимание, что Number.MIN_VALUE - это наименьшее возможное положительное число. наименьшее значение (т.е. меньше всего остального), вероятно, -Number.MAX_VALUE. - person Michael Scheper; 11.06.2014
comment
Это максимальное значение с плавающей запятой. Вопрос в наивысшем целочисленном значении. И хотя Number.MAX_VALUE является целым числом, вы не можете пройти мимо 2^53 без потери точности. - person Teepeemm; 23.07.2014
comment
@Teepeemm Это ответ почти шестилетней давности на вопрос почти шестилетней давности, поэтому любопытно, что вы позаботились о том, чтобы точнее стрелять по нему сейчас. Но если вы захотите посмотреть историю изменений, вы увидите, что в исходном вопросе не были указаны целые числа stackoverflow.com/posts / 307179 / revisions, не говоря уже о комментарии OP, всего в 4 комментариях, где он упоминает о внесении этого изменения / уточнения. - person Peter Bailey; 23.07.2014
comment
ES6 представляет Number.MIN_SAFE_INTEGER и Number.MAX_SAFE_INTEGER - person superlukas; 31.08.2014
comment
Итак, в этом случае, должны ли мы проголосовать против ответа, потому что он неверен для обновленного вопроса, или оставить его, потому что Питер Бейли был прав в то время, когда на него был дан ответ? - person rocketsarefast; 27.05.2015
comment
@Pacerier - хороший вопрос, который был проигнорирован: ответ оказался да: все соответствующие реализации ECMAscript должны вести себя так, как будто числа хранятся как числа с плавающей запятой двойной точности IEEE 754, поэтому все реализации должны давать одинаковые ответы на эти константы. - person Jules; 22.02.2018
comment
@rocketsarefast Я обновил текст ответа, включив в него информацию о ES6, но вы можете голосовать, как хотите. Я думаю, что здесь достаточно информации и разговоров о том, что голосование на данном этапе за такой старый вопрос / ответ в основном похоже на запрет. - person Peter Bailey; 01.03.2018
comment
Этот ответ в его нынешнем виде неверен, потому что он подразумевает, что MAX_SAFE_INTEGER и MAX_VALUE оба отвечают на вопрос, и что разница только в том, какие версии ES поддерживают их. Фактически только MAX_SAFE_INTEGER правильно отвечает на вопрос в его нынешнем виде, и только MAX_VALUE ответил на вопрос в том виде, в котором он был первоначально опубликован. MIN_SAFE_INTEGER и MIN_VALUE не имеют отношения к точному вопросу. - person Daira Hopwood; 17.10.2020

Это 2 53 == 9 007 199 254 740 992. Это связано с тем, что Numbers хранятся как числа с плавающей запятой в 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

person Vjeux    schedule 07.12.2010
comment
хотя никто никогда не достигнет конца этого цикла for в разумные сроки, вы можете сказать i += 1000000000 - person ninjagecko; 08.07.2015
comment
@ninjagecko, он начинает с MAX_INT, так что конец прямо здесь. Также использование i + = 1000000000 не сделает его бесконечным циклом. Попытайся. - person Ted Bigham; 05.01.2016
comment
@TedBigham: Ой, слишком быстро был готов к этому. Спасибо, что исправили меня дважды. - person ninjagecko; 05.01.2016
comment
См. Аргумент Джимми для 9,007,199,254,740,991 вместо 9,007,199,254,740,992 здесь. Это, в сочетании с моим продолжением, кажется убедительным. - person T.J. Crowder; 29.09.2018

В JavaScript есть число Infinity.

Примеры:

(Infinity>100)
=> true

// Also worth noting
Infinity - 1 == Infinity
=> true

Math.pow(2,1024) === Infinity
=> true

Этого может быть достаточно для некоторых вопросов по этой теме.

person BananaNeil    schedule 20.01.2012
comment
Что-то мне подсказывает, что бесконечность не считается целым числом. :) - person devios1; 20.09.2012
comment
Но достаточно инициализировать переменную min, когда вы ищете минимальное значение. - person djjeck; 24.10.2012
comment
Обратите внимание, что Infinity - 1 === Infinity - person H.Wolper; 18.10.2013
comment
также (Infinity ‹100) =› false и Math.pow (2,1024) === Infinity - person Sijav; 30.10.2013
comment
Math.pow (2,1024) === Бесконечность потрясающая. собираюсь добавить это. - person BananaNeil; 31.10.2013
comment
Также ничего не стоит, что он также обрабатывает отрицательную бесконечность. Таким образом, 1_ - person dmccabe; 06.11.2014
comment
в математике бесконечность - это не число, это понятие - person ; 25.09.2016
comment
Максимальное значение: Math.pow (2,1023) * 1,99999999999999998 - person Laxmikant Dange; 08.03.2017
comment
@ devios1 На самом деле это целое число, равное Infinity - 1 + 1. - person Andrew; 11.06.2020

Ответ Джимми правильно представляет непрерывный целочисленный спектр JavaScript от -9007199254740992 до 9007199254740992 инклюзивный (извините 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);

person Briguy37    schedule 24.07.2012
comment
@ CoolAJ86: Лол, я с нетерпением жду 15 марта 2040 года. Если наши цифры совпадают, мы должны устроить вечеринку :) - person Briguy37; 13.02.2013
comment
var x = Math.pow (2,53) -3; в то время как (x! = x + 1) x ++; - ›9007199254740991 - person MickLH; 18.11.2013
comment
@MickLH: я получаю 9007199254740992 с этим кодом. Какой движок JavaScript вы используете для тестирования? - person Briguy37; 18.11.2013
comment
Вы получаете 9007199254740992 с вашим собственным кодом, я использовал не окончательное значение x, а окончательную оценку x ++ по параноидальным причинам. Кстати, Google Chrome. - person MickLH; 18.11.2013
comment
@MickLH: оценка x++ дает вам значение x до того, как произошло приращение, так что, вероятно, это объясняет несоответствие. Если вы хотите, чтобы выражение оценивалось так же, как окончательное значение x, вы должны изменить его на ++x. - person peterflynn; 24.11.2013
comment
Спасибо, но я знаю семантику постинкремента и использовал его окончательную оценку (в отличие от окончательного значения x), потому что он предоставляет число, где (x! = X + 1), то есть последнее число, где +1 работает в отличие от первого числа, где он не работает - person MickLH; 25.11.2013
comment
@MickLH: "last number where +1 works" == "max number w/out losing precision" - 1 - person Briguy37; 25.11.2013
comment
1. на вопрос есть принятый ответ, поэтому ваше предположение о чем-то я не сказал либо неверно, либо бесполезно, объективно. 2. Цель моего комментария - показать, что большой алгоритм, который вы написали, - довольно бесполезная трата времени, добрый день, сэр. (Мне жаль, что вы так оскорбляетесь моим объяснением моей концепции с помощью очень похожего алгоритма, который также служит цели, которая действительно полезна для меня, также он вычисляет тот же X;)) - person MickLH; 25.11.2013
comment
@MickLH: Хорошо, я совершенно не понял, что вы пытались сказать. Я думал, что ваш первый алгоритм должен показать, что 9007199254740991 был правильным ответом. Вместо этого он должен был показать, что моя - бесполезная трата времени. Я рад, что мы это прояснили ... - person Briguy37; 26.11.2013
comment
Но люблю тебя, братан, не делай этого, как я злая задница, которая не ценит эту эффективность - person MickLH; 26.11.2013
comment
Не могли бы вы значительно ускорить это, начав с большого значения и проверяя только меньшие значения, когда вы теряете точность? Вместо добавления 1 за петлю, лол - person Marie; 20.07.2017

Чтобы быть в безопасности

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);
}());
person coolaj86    schedule 24.08.2011
comment
Вы не можете просто запустить его с 2 ^ 53-2, чтобы проверить? (да, можно, я просто попробовал, даже с -3 на всякий случай: var x = Math.pow (2,53) -3; while (x! = x + 1) x ++;) - ›9007199254740991 - person MickLH; 18.11.2013
comment
Хороший ответ! Более того, я знаю, что значение установлено, но почему бы не использовать двоичный поиск для его поиска? - person higuaro; 03.03.2014
comment
Что в этом интересного? Кроме того, @ Briguy37 опередил меня: stackoverflow.com/a/11639621/151312 - person coolaj86; 04.03.2014
comment
обратите внимание, что этот «безопасный» MAX_INT, основанный на 32 битах, не будет работать при сравнении со значениями Date. 4294967295 это так вчера! - person Jerry; 21.05.2014
comment
- 1; Меня это просто сбивало с толку. Иногда мне нравятся юмористические ответы, но я думаю, что вся эта тема достаточно сложна, особенно с учетом того, что некоторые читатели могут не знать, что целые числа хранятся как числа с плавающей запятой в JavaScript, или не понимать неточности с плавающей запятой, что добавляет забавный ответ на страницу, которая смешивает Правдивые претензии и дельный совет с глупостью - вредный ход. Кроме того, возможно, у меня просто плохое чувство юмора, но мне это не показалось смешным. - person Mark Amery; 26.12.2014
comment
Кроме того, я все еще совершенно не уверен, каковы ожидаемые проблемы со сдвигом битов. - person Mark Amery; 26.12.2014
comment
Ответ На всякий случай: var MAX_INT = 4294967295; не юмористический. Если вы не выполняете сдвиг битов, не беспокойтесь об этом (если вам не нужен int больше 4294967295, и в этом случае вам, вероятно, следует сохранить его как строку и использовать библиотеку bigint). - person coolaj86; 27.12.2014

Краткий ответ: «это зависит от обстоятельств».

Если вы где-то используете побитовые операторы (или если вы имеете в виду длину массива), диапазоны следующие:

Без подписи: 0…(-1>>>0)

Подпись: (-(-1>>>1)-1)…(-1>>>1)

(Так получилось, что побитовые операторы и максимальная длина массива ограничены 32-битными целыми числами.)

Если вы не используете побитовые операторы и не работаете с массивами длины:

Подпись: (-Math.pow(2,53))…(+Math.pow(2,53))

Эти ограничения налагаются внутренним представлением типа «Число», которое обычно соответствует представлению с плавающей запятой двойной точности IEEE 754. (Обратите внимание, что в отличие от типичных целых чисел со знаком, величина отрицательного предела такая же, как величина положительного предела, из-за характеристик внутреннего представления, которое фактически включает отрицательный 0!)

person danorton    schedule 17.07.2011
comment
Это ответ, на который я хотел наткнуться, о том, как преобразовать X в 32-битное целое число или целое число без знака. Проголосовал за ваш ответ. - person Charlie Affumigato; 24.11.2013

ECMAScript 6:

Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
person WaiKit Kung    schedule 31.03.2014
comment
Остерегайтесь это не (пока) поддерживается всеми браузерами! Сегодня это не нравится iOS (даже Chrome), Safari и IE. - person cregox; 07.05.2015
comment
Пожалуйста, прочтите ответ внимательно, мы не используем реализацию Number.MAX_SAFE_INTEGER по умолчанию в ECMAScript 6, мы определяем ее как Math.pow (2, 53) -1 - person WaiKit Kung; 08.05.2015
comment
Я думал, это просто ссылка на то, как это реализовано в ECMA 6! : P Я думаю, что мой комментарий все еще в силе. Все зависит от контекста. ;) - person cregox; 08.05.2015
comment
Насколько надежно вычислять MAX_SAFE_INTEGER во всех браузерах, работая в обратном направлении? Стоит ли вместо этого двигаться вперед? То есть Number.MAX_SAFE_INTEGER = 2 * (Math.pow (2, 52) - 1) + 1; - person kjv; 26.05.2015
comment
Math.pow(2, 53)-1 безопасная операция? Оно на единицу больше наибольшего безопасного целого числа. - person ioquatix; 13.03.2017
comment
Да, это вычисление верное. 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.

person Carr    schedule 11.03.2018

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

for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);

Это дает мне 9007199254740992 менее чем за миллисекунду в Chrome 30.

Он проверит степень двойки, чтобы определить, какая из них при «добавлении» 1 равна ему.

person Philippe97    schedule 05.10.2013
comment
«Это может привести к сбою вашего приложения», - подумал. - person Sapphire_Brick; 14.11.2019

Все, что вы хотите использовать для побитовых операций, должно находиться в диапазоне от 0x80000000 (-2147483648 или -2 ^ 31) до 0x7fffffff (2147483647 или 2 ^ 31-1).

Консоль сообщит вам, что 0x80000000 равно +2147483648, а 0x80000000 и 0x80000000 равно -2147483648.

person Scato    schedule 15.05.2012

Пытаться:

maxInt = -1 >>> 1

В Firefox 3.6 это 2 ^ 31-1.

person Martin Naatz    schedule 20.06.2010
comment
@danorton: Я не уверен, что вы понимаете, что делаете. ^ означает возведен во власть. В консоли javascript ^ является XOR, а не возведен в - person kumarharsh; 24.12.2013
comment
@Kumar, я не понимаю, что вы имеете в виду или какое другое значение «^» имеет отношение к этому вопросу о JavaScript. - person danorton; 25.12.2013
comment
откройте консоль Chrome / Firefox. Введите 5 ^ 2. В двоичном формате 5 - это 101, а 2 - это 010. Теперь, если вы выполните побитовое XOR, вы получите 5(101) ^ 2(010) = 7(111) ПРОЧИТАЙТЕ ЭТО, ЕСЛИ ВЫ ЗАБОТАЕТЕ Здесь обсуждается Math.pow(), а не ^ оператор - person kumarharsh; 25.12.2013
comment
Опять же, я совсем не запутался. Я прокомментировал и проголосовал против того, что написано. Если имеется в виду Math.pow (), то это и должно быть написано. В ответе на вопрос о JavaScript неуместно использовать синтаксис другого языка. Еще более неуместно использовать синтаксис, допустимый в JavaScript, но с интерпретацией в JavaScript, значение которой отличается от предполагаемого. - person danorton; 31.12.2013
comment
2 ^ 31 - это то, как в английском языке пишут два в тридцать первой степени. Это не в блоке кода. Вы бы пожаловались на кого-то, использующего; в ответ, потому что это символ с другим значением в Javascript? - person lmm; 05.03.2014
comment
Даже если следует написать 2³¹, а не 2 ^ 31 в виде обычного текста, обычно это делается, потому что большинство раскладок клавиатуры не имеют таких символы по умолчанию. По крайней мере, у меня не было проблем с пониманием того, что имел в виду этот ответ. - person Jocke; 03.06.2015
comment
Я собирался сказать: ^), но это заставило меня понять, что это не более чем отвратительная синтаксическая ошибка - person Gershy; 13.09.2019

На момент написания 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)

... но это работает.

person trincot    schedule 28.12.2018

Я провел простой тест с формулой X- (X + 1) = - 1, и наибольшее значение X, которое я могу получить для работы в Safari, Opera и Firefox (проверено на OS X), составляет 9e15. Вот код, который я использовал для тестирования:

javascript: alert(9e15-(9e15+1));
person Raynet    schedule 20.11.2008
comment
Обратите внимание, что 9e15 = 2 ^ 53 (см. Ответ @ Jimmy). - person Wedge; 21.11.2008
comment
9e15 = 9000000000000000. 2 ^ 53 = 9007199254740992. Следовательно, чтобы быть педантичным, 9e15 только приблизительно равно 2 ^ 53 (с двумя значащими цифрами). - person devios1; 20.09.2012
comment
@chaiguy В 9000000000000000 есть 1 значащая цифра. в `9007199254740992` 15 значащих цифр. - person Royi Namir; 13.11.2013
comment
@RoyiNamir Не хочу начинать здесь бессмысленную аргументацию, но 9000000000000000 имеет 16 значащих цифр. Если вы хотите только 1, это должно быть записано как 9x10 ^ 15. - person devios1; 13.11.2013
comment
@chaiguy Нет. 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;
person jerome    schedule 25.09.2014

Перейдем к источникам

Описание

Константа 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, а не как свойство Номер созданного вами объекта.

Совместимость с браузером

введите описание изображения здесь

person simhumileco    schedule 18.07.2018

В JavaScript числа представлены как 2^53 - 1.

Однако вычисляются Bitwise operation на 32 bits ( 4 bytes ), что означает, что если вы превысите 32-битную смену, вы начнете терять биты.

person Marwen Trabelsi    schedule 19.12.2018
comment
Это важный момент. Вот почему я здесь гуглю максимальный размер int. Другие ответы предполагают 53 бита, поэтому я закодировал его, думая, что могу безопасно выполнять побитовую арифметику положительных значений до 52 бит. Но это не удалось после 31 бита. Спасибо @Marwen - person JimbobTheSailor; 08.03.2021

Во встроенном javascript Google Chrome вы можете перейти примерно к 2 ^ 1024, прежде чем число будет называться бесконечным.

person Tommy    schedule 10.01.2012

Скато пишет:

все, что вы хотите использовать для побитовых операций, должно находиться в диапазоне от 0x80000000 (-2147483648 или -2 ^ 31) до 0x7fffffff (2147483647 или 2 ^ 31-1).

консоль сообщит вам, что 0x80000000 равно +2147483648, но 0x80000000 и 0x80000000 равно -2147483648

Шестнадцатеричные десятичные числа - это положительные значения без знака, поэтому 0x80000000 = 2147483648 - это математически правильно. Если вы хотите сделать это значение со знаком, вам нужно сдвинуть вправо: 0x80000000 >> 0 = -2147483648. Вы также можете написать 1 ‹---------------- 31.

person SammieFox    schedule 24.12.2016

Firefox 3, похоже, не имеет проблем с огромными числами.

1e + 200 * 1e + 100 рассчитывается как 1e + 300.

У Safari, похоже, тоже нет проблем с этим. (Для записи, это на Mac, если кто-то еще решит это проверить.)

Если только я не потерял мозг в это время суток, это намного больше, чем 64-битное целое число.

person jishi    schedule 20.11.2008
comment
это не 64-битное целое число, это 64-битное число с плавающей запятой, из которых 52/53 бита являются целой частью. поэтому он будет обрабатывать до 1e300, но не с точной точностью. - person Jimmy; 21.11.2008
comment
Джимми прав. Попробуйте это в своем браузере или в командной строке JS: 100000000000000010 - 1 => 100000000000000020 - person Ryan; 08.10.2011

Node.js и Google Chrome, похоже, используют 1024-битные значения с плавающей запятой, поэтому:

Number.MAX_VALUE = 1.7976931348623157e+308
person TinyTimZamboni    schedule 21.03.2013
comment
-1: максимальное представимое (не точное целое) число может быть ~ 2 ^ 1024, но это не означает, что они отклоняются от стандарта IEEE-754 64. - person Roy Tinker; 04.04.2013
comment
MAX_INT? Вы имеете в виду MAX_VALUE? - person Raul Guiu; 29.05.2013
comment
это максимальное значение с плавающей запятой. Это не значит, что вы можете хранить int так долго - person phuclv; 04.08.2013
comment
Или, что более важно, вы не можете надежно хранить такой длинный int без потери точности. 2^53 обозначается как MAX_SAFE_INT, потому что выше этой точки значения становятся приблизительными, так же как и дроби. - person IMSoP; 16.06.2014