Это определяется языком? Есть ли определенный максимум? Это отличается в разных браузерах?
1n << 10000n
это действительно очень большое целое число, без потери точности, без каких-либо зависимостей (и, разумеется, даже близко к пределу).
Это определяется языком? Есть ли определенный максимум? Это отличается в разных браузерах?
1n << 10000n
это действительно очень большое целое число, без потери точности, без каких-либо зависимостей (и, разумеется, даже близко к пределу).
Ответы:
JavaScript имеет два типа чисел: Number
и BigInt
.
Наиболее часто используемым типом чисел Number
является 64-битное число IEEE 754 с плавающей запятой .
Наибольшее точное целочисленное значение этого типа Number.MAX_SAFE_INTEGER
:
Для сравнения: один квадриллион байтов - это петабайт (или тысяча терабайт).
«Безопасный» в данном контексте относится к способности точно представлять целые числа и правильно их сравнивать.
Обратите внимание, что все положительные и отрицательные целые числа, величина которых не превышает 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.
4294967295 === Math.pow(2,32) - 1;
> = ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
<= ES5
Из ссылки :
Number.MAX_VALUE;
Number.MIN_VALUE;
Number.MIN_VALUE
это наименьшее возможное положительное число. Мере значение (то есть меньше , чем все остальное), вероятно -Number.MAX_VALUE
.
Number.MIN_SAFE_INTEGER
иNumber.MAX_SAFE_INTEGER
Это 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
В JavaScript есть номер с именем Infinity
.
Примеры:
(Infinity>100)
=> true
// Also worth noting
Infinity - 1 == Infinity
=> true
Math.pow(2,1024) === Infinity
=> true
Это может быть достаточно для некоторых вопросов, касающихся этой темы.
min
переменную, когда вы ищете минимальное значение.
Infinity - 1 === Infinity
1 - Infinity === -Infinity
Ответ Джимми правильно представляет непрерывный целочисленный спектр 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);
x++
дает вам значение x до того, как произошло увеличение, что, вероятно, объясняет расхождение. Если вы хотите, чтобы выражение оценивалось так же, как и конечное значение x, вы должны изменить его на ++x
.
var MAX_INT = 4294967295;
Я думал, что я был бы умен и нашел бы ценность x + 1 === x
с более прагматичным подходом.
Моя машина может считать только 10 миллионов в секунду или около того ... поэтому я отправлю ответ с окончательным ответом через 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;
Math.pow(2, 53)-1
безопасная операция? Это больше, чем наибольшее безопасное целое число.
Многие ответы от прежних времен показали результат true
от 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 и смежная точка радиуса , затем, умножая 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 has 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 раза от дроби , это означает, что теперь каждое 1 добавление в части дроби фактически равно 2 сложению, поэтому double 64-битный двоичный формат -precision не может содержать нечетные числа, если число больше 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 --|
Битовое значение 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
// 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.
Другие, возможно, уже дали общий ответ, но я подумал, что было бы неплохо дать быстрый способ его определения:
for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);
Что дает мне 9007199254740992 менее чем за миллисекунду в Chrome 30.
Он проверит степени 2, чтобы определить, какой из них, когда «добавлен» 1, равен себе.
Пытаться:
maxInt = -1 >>> 1
В Firefox 3.6 это 2 ^ 31 - 1.
^
значит возведен во власть . В консоли javascript ^
есть XOR , а не повышен до
101
2, а 2 - это 010
. Теперь, если вы побитируете их XOR, вы получите 5(101) ^ 2(010) = 7(111)
ПРОЧИТАЙТЕ ЭТО, ЕСЛИ ВЫ ЗАМЕДЛЕНЫ То, что обсуждается здесь, Math.pow()
не ^
оператор
На момент написания, 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, и наибольшее значение XI, которое можно получить для работы в Safari, Opera и Firefox (протестировано в OS X) - 9e15. Вот код, который я использовал для тестирования:
javascript: alert(9e15-(9e15+1));
9000000000000000
1 значимая цифра. в `9007199254740992` есть 15 значимых цифр.
9000000000000000
как есть - есть 1
SF. где 90*10^14
есть 2. ( sigfigscalculator.appspot.com ) & mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (нижняя часть)
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
будет оцениваться как true, что математически неверно. Видеть Number.isSafeInteger () для получения дополнительной информации.Поскольку
MAX_SAFE_INTEGER
статическое свойство Number , Вы всегда используете его какNumber.MAX_SAFE_INTEGER
, а не как свойство Number созданного вами объекта .
Во встроенном javascript Google Chrome вы можете перейти примерно к 2 ^ 1024, прежде чем число будет называться бесконечностью.
В JavaScript представление чисел есть 2^53 - 1
.
Тем не менее , Bitwise operation
они рассчитаны на то 32 bits ( 4 bytes )
, что если вы превышаете 32-битные смены, вы начнете терять биты
Scato wrotes:
все, что вы хотите использовать для побитовых операций, должно быть между 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
Node.js и Google Chrome, похоже, используют 1024-битные значения с плавающей запятой, поэтому:
Number.MAX_VALUE = 1.7976931348623157e+308
2^53
упоминается как MAX_SAFE_INT
потому, что выше этой точки значения становятся приближениями, так же, как и дроби.