En Javascript, crear variables numéricas es muy sencillo, pero hay muchísimos matices que se deben conocer y que necesitamos dominar para trabajar correctamente con números y anticiparnos a posibles situaciones.
¿Qué es una variable numérica?
En Javascript, los números son uno de los tipos de datos básicos (tipos primitivos), que, para crearlos, simplemente basta con escribirlos literalmente. No obstante, como en Javascript todo se puede representar con objetos (como veremos más adelante) también se pueden declarar mediante la palabra clave new
:
Constructor | Descripción |
---|---|
new Number(number) | Crea un objeto numérico a partir del número number pasado por parámetro. |
number | Simplemente, el número en cuestión. Notación preferida. |
Sin embargo, aunque existan estas dos formas de declararlas, no se suele utilizar la notación new
con números, ya que es bastante más tedioso y complicado, por lo que lo preferible es utilizar la notación de literales:
// Notación literal (preferida)
const number = 4;
const decimal = 15.8;
const legibleNumber = 5_000_000;
// Notación con objetos (evitar)
const number = new Number(4);
const decimal = new Number(15.8);
const letter = new Number("A");
Observa que los números con decimales, en Javascript los separamos con un punto ( .
), mientras que de forma opcional, podemos utilizar el guión bajo ( _
) para separar visualmente y reconocer las magnitudes que usamos, teniendo en cuenta que para Javascript es lo mismo:
5_000_000 === 5000000; // true
Cualquier parámetro pasado al new Number()
que no sea un número (por ejemplo, la "A"
), dará como resultado un valor NaN
(Not A Number), algo en lo que profundizaremos un poco más adelante, en el tema ¿Qué es NaN (Not A Number)?.
También hay casos, donde un número muy grande (o muy pequeño) tenga un comportamiento extraño, como el siguiente:
const incorrectNumber = 482598752875287528533; // 482598752875287540000 (Diferente)
const bigNumber = 482598752875287528533n; // 482598752875287528533n (El mismo)
Observa que incorrectNumber
no muestra realmente el mismo número, sino que es diferente. Sin embargo, si le añadimos una n
al final, si que guarda la cantidad exacta.
En el primer caso, estamos guardando un número más grande de los que Javascript puede representar, entonces pierde precisión. Hablaremos de ello en el siguiente apartado.
En el segundo caso, en lugar de crear un tipo
Number
, añadiendo lan
creamos un tipoBigInt
, del que hablaremos más adelante, en el tema BigInt en Javascript.
Rangos numéricos seguros
Algo que hay que tener muy claro en Javascript (y en general, en programación, ya que no es algo propio de Javascript) es que cuando trabajamos con datos numéricos, es posible que ciertos números no se puedan representar exactamente, y no sean tan precisos como nos gustaría. Esto ocurre porque se guardan en un formato llamado coma flotante de doble precisión.
Observa la siguiente gráfica donde se puede ver claramente:
Fíjate en la gráfica de color inferior:
- Los números en la franja verde se pueden usar con seguridad.
- Los números en la franja amarilla al operarse con otros podrían no ser seguros.
- Los números de la franja roja no se pueden representar.
Existe una serie de constantes definidas en relación a este tema, que marcan los límites mínimo o máximo. Veamos cuales son y su significado:
Constante | Valor en Javascript | Descripción |
---|---|---|
Number.MAX_VALUE | ~ 2 1024 | Valor más grande |
Number.MIN_VALUE | ~ 5×10 -324 | Valor más pequeño |
Number.MAX_SAFE_INTEGER | 2 53 -1 | Valor seguro más grande |
Number.MIN_SAFE_INTEGER | -(2 53 -1) | Valor seguro más pequeño |
Number.EPSILON | 2 -52 | Número muy pequeño: ε |
El valor Number.EPSILON
es un número que se suele utilizar para representar cantidades matemáticas muy pequeñas. Por otro lado, la diferencia entre Number.MAX_VALUE
y Number.MAX_SAFE_INTEGER
es que, el primero es el valor máximo que es posible representar en Javascript. Por otro lado, el segundo es el valor máximo para realizar cálculos con seguridad en Javascript.
Los lenguajes de programación están sujetos a la precisión numérica debido a la forma interna en la que guardan valores numéricos. Si necesitamos realizar operaciones con muy alta precisión numérica en Javascript, se recomienda utilizar el tipo de dato BigInt, o librerías de terceros como decimal.js o bigNumber.js.
Valores infinitos en Javascript
Si simplemente quieres representar un número muy alto, sin importar el valor en sí, puedes utilizar la constante Infinity
. De la misma forma, la constante -Infinity
se puede utilizar para valores muy bajos donde no importa el valor en sí:
Constante | Valor en Javascript | Descripción |
---|---|---|
Number.POSITIVE_INFINITY | Infinity | Infinito positivo: +∞ |
Number.NEGATIVE_INFINITY | -Infinity | Infinito negativo: -∞ |
Los valores infinitos se pueden operar con números, pero ten en cuenta las reglas de los infinitos, y que en algunos casos, puede resultar una indeterminación, por lo que nos dará como resultado NaN
(not a number).
Comprobaciones numéricas
Si queremos conocer la naturaleza de una variable numérica (número finito, número entero o número seguro), las podemos comprobar con uno de los métodos estáticos de Number
que tenemos a continuación:
Método | Descripción |
---|---|
Number.isFinite(number) | Comprueba si number es un número finito. |
Number.isInteger(number) | Comprueba si number es un número entero. |
Number.isSafeInteger(number) | Comprueba si number es un número seguro. |
Ten en cuenta que estas funciones devuelven un
// ¿Número finito?
Number.isFinite(42); // true
Number.isFinite(551.3); // true
Number.isFinite(Infinity); // false, es infinito
// ¿Número entero?
Number.isInteger(5); // true
Number.isInteger(4.6); // false, es decimal
// ¿Número seguro?
Number.isSafeInteger(1e15); // true (valor en la franja verde)
Number.isSafeInteger(1e16); // false (valor en la franja amarilla)
1e309 === Infinity; // true
Number.isSafeInteger(1e309); // false (valor en la franja roja)
Ten en cuenta que la notación 1e5
significa «5 ceros seguidos de un 1», es decir, 100000
.
Representación numérica
En Javascript tenemos dos formas de representar los números: la notación exponencial (basada en potencias de 10) y la notación de punto fijo (una cantidad de dígitos para la parte entera, y otra para la parte decimal).
Podemos cambiar entre ellas utilizando los siguientes métodos:
Método | Descripción |
---|---|
.toExponential(digits) | Convierte el número a notación exponencial con digits decimales. |
.toFixed(digits) | Convierte el número a notación de punto fijo con digits decimales. |
.toPrecision(size) | Utiliza size dígitos de precisión en el número. |
Además, observa el método .toPrecision()
mediante el cuál puedes cambiar la precisión de un número. Observemos ahora el siguiente ejemplo aplicando las funciones anteriores al número decimal 1.25
y al 523.75
para cambiar la precisión:
// Notación exponencial
(1.25).toExponential(0); // "1e+0"
(1.25).toExponential(1); // "1.3e+0"
(1.25).toExponential(2); // "1.25e+0"
(1.25).toExponential(3); // "1.250e+0"
// Notación punto fijo
(1.25).toFixed(0); // "1"
(1.25).toFixed(1); // "1.3"
(1.25).toFixed(2); // "1.25"
(1.25).toFixed(3); // "1.250"
// Cambiando precisión
(523.75).toPrecision(1); // "5e+2"
(523.75).toPrecision(2); // "5.2e+2"
(523.75).toPrecision(3); // "524"
(523.75).toPrecision(4); // "523.8"
(523.75).toPrecision(5); // "523.75"
No olvides que en todos los casos, el número se convierte a tipo de dato