1.1 Redondeo de números flotantes
Los números flotantes en inglés se llaman floating point number – números de punto flotante: en EE.UU. se utiliza un punto para separar la parte entera de la decimal. De ahí viene el nombre float.
Como ya vimos, al convertir un número flotante (float) a entero (int), siempre se redondea hacia abajo hasta el entero — simplemente se descarta su parte decimal. Y es fácil imaginar una situación en la que se quiera redondear el número flotante simplemente al entero más cercano o incluso hacia arriba. ¿Qué hacer?
Para este caso, en JavaScript existe la función incorporada round(). La inventaron antes de crear la biblioteca Math, por lo que no forma parte de ella. Las funciones para redondear hacia abajo y hacia arriba se encuentran en la biblioteca math.
Función Math.round()
La función Math.round() redondea el número al entero más cercano:
Math.round(número_flotante)
Esta función devolverá el número entero más cercano al número flotante pasado.
Ejemplos:
| Comando | Resultado |
|---|---|
let x = Math.round(4.1); |
4 |
let x = Math.round(4.5); |
5 |
let x = Math.round(4.9); |
5 |
Función Math.ceil()
La función Math.ceil() redondea el número hacia arriba:
| Comando | Resultado |
|---|---|
let x = Math.ceil(4.1); |
5 |
let x = Math.ceil(4.5); |
5 |
let x = Math.ceil(4.9); |
5 |
Función Math.floor()
La función Math.floor() redondea el número hacia abajo:
| Comando | Resultado |
|---|---|
let x = Math.floor(4.1); |
4 |
let x = Math.floor(4.5); |
4 |
let x = Math.floor(4.9); |
4 |
Si te cuesta recordar estos comandos, te puede ayudar una pequeña lección de inglés:
- math — matemáticas
- round — redondear
- ceiling — techo
- floor — suelo
1.2 Estructura de los números de punto flotante
El tipo number en JavaScript puede almacenar valores en el rango de -1.7*10308 a +1.7*10308. Este rango gigantesco de valores se explica porque el tipo number está construido de manera diferente en comparación con los tipos enteros. Cada variable de tipo number contiene dos números: el primero se llama mantisa, y el segundo — exponente.
Supongamos que tenemos el número 123456789, y lo guardamos en una variable de tipo number. Entonces el número será transformado a la forma 1.23456789*108, y dentro del tipo number se almacenarán los números — 1.23456789 y 8. En rojo está marcada la “parte significativa del número” (mantisa), en azul — el exponente.
Este enfoque permite almacenar tanto números muy grandes como muy pequeños. Pero como el tamaño del número está limitado a 8 bytes (64 bits) y parte de los bits se utiliza para almacenar el exponente (así como el signo del número y el signo del exponente), la longitud máxima de la mantisa está limitada a 15 dígitos.
Esta es una descripción muy simplificada de la estructura de los números flotantes: se puede encontrar una más completa en este enlace.
1.3 Pérdida de precisión al trabajar con números flotantes
Al trabajar con números flotantes siempre se debe tener en cuenta que los números flotantes son inexactos. Siempre habrá errores de redondeo, errores de conversión del sistema decimal al binario y, finalmente, lo más común — pérdida de precisión al sumar/restar números de dimensiones muy diferentes.
Lo último es la situación más inesperada para los principiantes en programación.
Si restamos de un número 109 1/109, obtenemos de nuevo 109.
| Restar números de dimensiones muy diferentes | Explicación |
|---|---|
| 1000000000.000000000 - 0.000000001 1000000000.000000000 |
El segundo número es demasiado pequeño, y su parte significativa se ignora (resaltado en gris). En rojo se muestran 15 dígitos significativos. |
Qué decir, la programación no es matemáticas.
1.4 Peligro de comparar números flotantes
Otra trampa acecha a los programadores al comparar números flotantes. Dado que al trabajar con estos números pueden acumularse errores de redondeo, pueden ocurrir situaciones en las que los números flotantes deberían ser iguales, pero no lo son. Y al revés: los números deberían ser diferentes, pero son iguales.
Ejemplo:
| Comando | Explicación |
|---|---|
let a = 1000000000.0let b = 0.000000001let c = a – b |
En la variable a estará el valor 1000000000.0.En la variable c estará el valor 1000000000.0(el número en la variable b es demasiado pequeño). |
En el ejemplo anterior, a y c no deberían ser iguales, pero lo son.
O tomemos otro ejemplo:
| Comando | Explicación |
|---|---|
let a = 1.00000000000000001let b = 1.00000000000000002 |
En la variable a estará el valor 1.0.En la variable b estará el valor 1.0. |
En la práctica, los números flotantes se comparan así:
Si la diferencia de los números (en valor absoluto) es menor que un número muy pequeño, se consideran iguales.
Ejemplo:
let a = 0.00000000012;
let b = 0.000000000011;
if (Math.abs(a - b) < 0.00001) {
console.log("son iguales");
} else {
console.log("no son iguales");
}
GO TO FULL VERSION