¿Está esto definido por el idioma? ¿Hay un máximo definido? ¿Es diferente en diferentes navegadores?
1n << 10000n
es un número muy, muy grande, sin perder precisión, sin necesidad de dependencias (y ni que decir, ni siquiera cerca de un límite).
¿Está esto definido por el idioma? ¿Hay un máximo definido? ¿Es diferente en diferentes navegadores?
1n << 10000n
es un número muy, muy grande, sin perder precisión, sin necesidad de dependencias (y ni que decir, ni siquiera cerca de un límite).
Respuestas:
JavaScript tiene dos tipos de números: Number
y BigInt
.
El tipo de número más utilizado Number
, es un número IEEE 754 de coma flotante de 64 bits .
El valor integral exacto más grande de este tipo es Number.MAX_SAFE_INTEGER
, que es:
Para poner esto en perspectiva: un billón de bytes es un petabyte (o mil terabytes).
"Seguro" en este contexto se refiere a la capacidad de representar enteros exactamente y compararlos correctamente.
Tenga en cuenta que todos los enteros positivos y negativos cuya magnitud no es mayor que 2 53 son representables en el
Number
tipo (de hecho, el entero 0 tiene dos representaciones, +0 y -0).
Para usar de forma segura enteros más grandes que esto, debe usar BigInt
, que no tiene límite superior.
Tenga en cuenta que los operadores bit a bit y los operadores de desplazamiento operan con enteros de 32 bits, por lo que en ese caso, el entero seguro máximo es 2 31 -1, o 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
Nota técnica sobre el tema del número 9,007,199,254,740,992: Hay una representación exacta de IEEE-754 de este valor, y puede asignar y leer este valor desde una variable, por lo tanto, para aplicaciones cuidadosamente seleccionadas en el dominio de enteros menores o iguales a este valor, podría tratarlo como un valor máximo.
En el caso general, debe tratar este valor IEEE-754 como inexacto, porque es ambiguo si está codificando el valor lógico 9,007,199,254,740,992 o 9,007,199,254,740,993.
4294967295 === Math.pow(2,32) - 1;
> = ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
<= ES5
De la referencia :
Number.MAX_VALUE;
Number.MIN_VALUE;
Number.MIN_VALUE
es el número positivo más pequeño posible . El menor valor (es decir, menos que cualquier otra cosa) es probablemente -Number.MAX_VALUE
.
Number.MIN_SAFE_INTEGER
yNumber.MAX_SAFE_INTEGER
Es 2 53 == 9 007 199 254 740 992. Esto se debe a que los Number
s se almacenan como coma flotante en una mantisa de 52 bits.
El valor mínimo es -2 53 .
Esto hace que pasen cosas divertidas
Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true
Y también puede ser peligroso :)
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
}
Leer más: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
i += 1000000000
En JavaScript, hay un número llamado Infinity
.
Ejemplos:
(Infinity>100)
=> true
// Also worth noting
Infinity - 1 == Infinity
=> true
Math.pow(2,1024) === Infinity
=> true
Esto puede ser suficiente para algunas preguntas sobre este tema.
min
variable cuando buscas un valor mínimo.
Infinity - 1 === Infinity
1 - Infinity === -Infinity
La respuesta de Jimmy representa correctamente el espectro entero continuo de JavaScript como -9007199254740992 a 9007199254740992 inclusive (perdón 9007199254740993, ¡podrías pensar que eres 9007199254740993, pero estás equivocado! Demostración debajo o en jsfiddle ).
console.log(9007199254740993);
Sin embargo, no hay una respuesta que encuentre / pruebe esto programáticamente (aparte de la que CoolAJ86 aludió en su respuesta que terminaría en 28.56 años;), así que aquí hay una forma un poco más eficiente de hacerlo (para ser precisos, es más eficiente por aproximadamente 28.559999999968312 años :), junto con un violín de prueba :
/**
* 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++
le da el valor de x antes de que ocurra el incremento, por lo que eso probablemente explica la discrepancia. Si desea que la expresión se evalúe de la misma manera que el valor final de x, debe cambiarla a ++x
.
var MAX_INT = 4294967295;
Pensé que sería inteligente y encontraría el valor en el que x + 1 === x
con un enfoque más pragmático.
Mi máquina solo puede contar con 10 millones por segundo más o menos ... así que volveré a publicar con la respuesta definitiva en 28.56 años.
Si no puedes esperar tanto, estoy dispuesto a apostar que
9007199254740992 === Math.pow(2, 53) + 1
es prueba suficiente4294967295
que es Math.pow(2,32) - 1
para evitar los problemas esperados con el desplazamiento de bitsEncontrar 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);
}());
La respuesta corta es "depende".
Si está utilizando operadores bit a bit en cualquier lugar (o si se refiere a la longitud de una matriz), los rangos son:
No firmado: 0…(-1>>>0)
Firmado: (-(-1>>>1)-1)…(-1>>>1)
(Sucede que los operadores bit a bit y la longitud máxima de una matriz están restringidos a enteros de 32 bits).
Si no está utilizando operadores bit a bit o trabajando con longitudes de matriz:
Firmado: (-Math.pow(2,53))…(+Math.pow(2,53))
Estas limitaciones están impuestas por la representación interna del tipo "Número", que generalmente corresponde a la representación de punto flotante de precisión doble IEEE 754. (Tenga en cuenta que, a diferencia de los enteros con signo típicos, la magnitud del límite negativo es la misma que la magnitud del límite positivo, debido a las características de la representación interna, que en realidad incluye un 0 negativo ).
ECMAScript 6:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
MAX_SAFE_INTEGER
en todos los navegadores trabajando hacia atrás? ¿Deberías avanzar en su lugar? Es decir, Number.MAX_SAFE_INTEGER = 2 * (Math.pow (2, 52) - 1) + 1;
Math.pow(2, 53)-1
una operación segura? Va uno más grande que el mayor entero seguro.
Muchas respuestas de épocas anteriores han mostrado el resultado true
de 9007199254740992 === 9007199254740992 + 1
verificar que 9 007 199 254 740 991 es el número entero máximo y seguro.
¿Qué pasa si seguimos haciendo acumulación?
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
Podríamos descubrir que entre los números mayores que 9 007 199 254 740 992 , solo los números pares son representables .
Es una entrada para explicar cómo funciona el formato binario de doble precisión de 64 bits en esto. Veamos cómo se mantiene (representa) 9 007 199 254 740 992 utilizando este formato binario.
Usando una versión breve para demostrarlo de 4 503 599 627 370 496 :
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
En el lado izquierdo de la flecha, tenemos el valor de bit 1 y un punto de raíz adyacente , luego, al multiplicar 2^52
, movemos a la derecha el punto de raíz 52 pasos, y llega al final. Ahora tenemos 4503599627370496 en binario.
Ahora comenzamos a acumular 1 a este valor hasta que todos los bits se establezcan en 1, lo que equivale a 9 007 199 254 740 991 en decimal.
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.
Ahora, debido a que en formato binario de 64 bits de doble precisión , asigna estrictamente 52 bits por fracción, no hay más bits disponibles para sumar uno más, así que lo que podemos hacer es establecer todos los bits nuevamente en 0, y manipular la parte exponente:
|--> 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 --|
Ahora obtenemos el 9 007 199 254 740 992 , y con el número mayor que él, lo que el formato podría contener es 2 veces la fracción , significa que ahora cada 1 suma en la parte de la fracción en realidad equivale a 2 sumas, por eso el doble -precisión de formato binario de 64 bits no puede contener números impares cuando el número es mayor que 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 --|
Entonces, cuando el número llega a ser mayor que 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, solo se pueden mantener 4 veces la fracción :
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
¿Qué tal el número entre [ 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 --|
El valor de bit 1 después del punto de raíz es 2 ^ -1 exactamente. (= 1/2 , = 0.5) Entonces, cuando el número es menor que 4 503 599 627 370 496 (2 ^ 52), hay un bit disponible para representar las 1/2 veces del entero :
input: 4503599627370495.5 output: 4503599627370495.5
input: 4503599627370495.75 output: 4503599627370495.5
Menos de 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"
¿Y cuál es el rango disponible de la parte exponente ? el formato le asigna 11 bits. Formato completo de Wiki : (Para más detalles, vaya allí)
Entonces, para que la parte del exponente sea 2 ^ 52, necesitamos exactamente establecer e = 1075.
Puede que otros ya hayan dado la respuesta genérica, pero pensé que sería una buena idea dar una forma rápida de determinarla:
for (var x = 2; x + 1 !== x; x *= 2);
console.log(x);
Lo que me da 9007199254740992 en menos de un milisegundo en Chrome 30.
Pondrá a prueba las potencias de 2 para encontrar cuál, cuando se 'agrega' 1, es igual a sí mismo.
Tratar:
maxInt = -1 >>> 1
En Firefox 3.6 es 2 ^ 31-1.
^
significa elevado al poder . En la consola javascript, ^
es XOR , no elevado a
101
y 2 es 010
. Ahora, si los haces Bitwise XOR, 5(101) ^ 2(010) = 7(111)
LEERÁS ESTO SI ESTÁS CONFUNDIDO Lo que se está discutiendo aquí Math.pow()
no es el ^
operador
En el momento de la escritura, JavaScript está recibiendo un nuevo tipo de datos: BigInt
. Es una propuesta TC39 en la etapa 4 que se incluirá en EcmaScript 2020 . BigInt
está disponible en Chrome 67+, FireFox 68+, Opera 54 y Node 10.4.0. Está en marcha en Safari, et al ... Introduce literales numéricos con un sufijo "n" y permite una precisión arbitraria:
var a = 123456789012345678901012345678901n;
La precisión aún se perderá, por supuesto, cuando dicho número se coaccione (tal vez involuntariamente) a un tipo de datos numérico.
Y, obviamente, siempre habrá limitaciones de precisión debido a la memoria finita y un costo en términos de tiempo para asignar la memoria necesaria y realizar operaciones aritméticas en números tan grandes.
Por ejemplo, la generación de un número con cien mil dígitos decimales tardará notablemente antes de completarse:
console.log(BigInt("1".padEnd(100000,"0")) + 1n)
...pero funciona.
Hice una prueba simple con una fórmula, X- (X + 1) = - 1, y el mayor valor de XI puede funcionar en Safari, Opera y Firefox (probado en OS X) es 9e15. Aquí está el código que usé para probar:
javascript: alert(9e15-(9e15+1));
9000000000000000
hay 1 cifra significativa. en `9007199254740992` hay 15 cifras significativas.
9000000000000000
tal como está - tiene 1
SF. donde 90*10^14
tiene 2. ( sigfigscalculator.appspot.com ) y mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (sección inferior)
La
MAX_SAFE_INTEGER
constante tiene un valor de9007199254740991
(9,007,199,254,740,991 o ~ 9 billones). El razonamiento detrás de ese número es que JavaScript usa números de formato de punto flotante de doble precisión como se especifica en IEEE 754 y solo puede representar con seguridad números entre-(2^53 - 1)
y2^53 - 1
.Seguro en este contexto se refiere a la capacidad de representar enteros exactamente y compararlos correctamente. Por ejemplo,
Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2
evaluará a verdadero, que es matemáticamente incorrecto. Consulte Number.isSafeInteger () para obtener más información.Debido a que
MAX_SAFE_INTEGER
es una propiedad estática de Number , siempre la usa comoNumber.MAX_SAFE_INTEGER
, en lugar de como una propiedad de un objeto Number que creó.
En el javascript incorporado de Google Chrome, puede ir a aproximadamente 2 ^ 1024 antes de que el número se llame infinito.
En JavaScript, la representación de los números es 2^53 - 1
.
Scato escribe:
todo lo que desee usar para operaciones bit a bit debe estar entre 0x80000000 (-2147483648 o -2 ^ 31) y 0x7fffffff (2147483647 o 2 ^ 31 - 1).
la consola le dirá que 0x80000000 es igual a +2147483648, pero 0x80000000 y 0x80000000 es igual a -2147483648
Los decimales hexadecimales son valores positivos sin signo, por lo que 0x80000000 = 2147483648, eso es matemáticamente correcto. Si desea convertirlo en un valor firmado, debe desplazarse a la derecha: 0x80000000 >> 0 = -2147483648. También puedes escribir 1 << 31.
Firefox 3 no parece tener un problema con grandes números.
1e + 200 * 1e + 100 calculará bien a 1e + 300.
Safari parece no tener problemas con eso también. (Para el registro, esto está en una Mac si alguien más decide probar esto).
A menos que pierda mi cerebro a esta hora del día, esto es mucho más grande que un entero de 64 bits.
100000000000000010 - 1 => 100000000000000020
Node.js y Google Chrome parecen estar utilizando valores de coma flotante de 1024 bits, por lo que:
Number.MAX_VALUE = 1.7976931348623157e+308
2^53
se conoce como MAX_SAFE_INT
porque arriba de ese punto los valores se convierten en aproximaciones, de la misma manera que lo son las fracciones.