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

это определяется языком? Существует ли определенный максимум? Отличается ли это в разных браузерах?

21 ответов


+/- 9007199254740991

ECMA раздел 8.5-Numbers

обратите внимание, что все положительные и отрицательные целые числа, величина которых не превышает 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. Это потому что Numbers хранятся как с плавающей запятой в 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: (для получения более подробной информации, пожалуйста, перейдите туда)

IEEE 754 Double Floating Point Format.svg

enter image description here

поэтому, чтобы получить 2^52 в экспоненциальной части, нам точно нужно установить e = 1075.


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

javascript: alert(9e15-(9e15+1));

попробуй:

maxInt = -1 >>> 1

в Firefox 3.6 это 2^31 - 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, а не как свойство объект, который вы создали.

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

enter image description here


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

1e + 200 * 1e + 100 рассчитает штраф до 1e + 300.

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

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


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

Number.MAX_VALUE = 1.7976931348623157e+308