Максимальное целочисленное значение в JavaScript

Я читаю вторую главу книги Eloquent JavaScript. Автор утверждает, что:

Any whole number less than 2^52 (which is more than 10^15) will safely fit in a JavaScript number.

Я схватил значение 2 ^ 52 из wikipedia.

4,503,599,627,370,496

Значение должно быть меньше 2 ^ 52, поэтому я вычитал 1 из начального значения;

var max = 4503599627370495;

После определения максимальной переменной я проверяю, какое значение (я использую Chrome 32.0.1700.77).

console.log(max); // 4503599627370495

Я хотел бы видеть, что происходит, когда я перехожу к этому пределу, поэтому я добавляю его пару раз.

Неожиданный:

max += 1;
console.log(max); // 4503599627370496
max += 1;
console.log(max); // 4503599627370497
max += 1;
console.log(max); // 4503599627370498

Я преодолел предел, и расчеты все еще точны.

Я попробовал следующую мощность вместо двух, 2 ^ 53, на этот раз я не вычитал 1:

9,007,199,254,740,992

var max = 9007199254740992;

Этот, кажется, больший предел, кажется, что я вполне могу добавить и вычитать числа:

max += 1;
console.log(max); // 9007199254740992
max += 1;
console.log(max); // 9007199254740992
max -= 1;
console.log(max); // 9007199254740991
max += 1;
console.log(max); // 9007199254740992
max -= 900;
console.log(max); // 9007199254740092
max += 900;
console.log(max); // 9007199254740992

Я могу назначить даже большее значение max, однако оно теряет точность, и я не могу безопасно добавить или вычитать числа снова.

Не могли бы вы точно объяснить механизм, который находится под капотом? Пример того, что происходит с битами после перехода выше 2 ^ 52, будет действительно полезен.

Ответ 1

Это не строго типизированный язык программирования. JS имеет объект Number. Вы можете даже получить бесконечное число: document.write(Math.exp(1000));.

document.write(Number.MIN_VALUE + "<br>");
document.write(Number.MAX_VALUE + "<br>");

document.write(Number.POSITIVE_INFINITY + "<br>");
document.write(Number.NEGATIVE_INFINITY + "<br>");

    alert([
         Number.MAX_VALUE/(1e293),
         Number.MAX_VALUE/(1e292),
         Number.MAX_VALUE/(1e291),
         Number.MAX_VALUE/(1e290),
    ].join('\n'))

Надеюсь, это полезный ответ. Спасибо!

UPDATE: max int is - +/- 9007199254740992

Ответ 2

Здесь вы можете найти некоторую информацию о типе номера JavaScript: ECMA-262 5th Edition: Тип номера.

Как упоминается, числа представлены в виде 64-битного числа с плавающей запятой, с 53 битами мантиссы (значащие цифры) и 11 бит для показателя (IEEE 754). Результат затем получается с помощью показателя мантиссы * 2 ^.

Это означает, что в мантиссе могут быть представлены значения до 2 ^ 53 (из них несколько чисел имеют особые значения, а остальные - положительные и отрицательные целые числа).

Число 2 ^ 53 (9007199254740992) не может быть представлено в мантиссе, и вы должны использовать показатель степени. В качестве примера вы можете представить 2 ^ 53 как (9007199254740992 / 2) * 2^1, т.е. mantissa = 9007199254740992 / 2 = 4503599627370496 и exponent = 1.

Проверьте, что происходит с 2 ^ 53 + 1 (9007199254740993). Здесь мы должны сделать то же самое, mantissa = 9007199254740993 / 2 = 4503599627370496. Ой, разве это не та самая мантисса, которую мы имели за 2 ^ 53? Похоже, произошла ошибка округления!:)

(Примечание: приведенные выше примеры на самом деле не так, как это работает: мантисса всегда интерпретируется как имеющая точку после первой цифры, что означает, что, например, число 3 фактически хранится как 1.5*2. в приведенном выше объяснении, чтобы было легче следовать.)

Вы можете найти дополнительную информацию о числах с плавающей запятой (в общем) здесь: Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой.

Ответ 3

Вы можете думать о 52 битах целого числа в JS, но помните, что побитовые логические операторы & | >> и т.д. будут иметь дело только с 32 менее значимыми битами, отбрасывающими остальные.