1. Redondeo de números reales
Como ya hemos discutido, cuando se asigna un número real a una int
variable, siempre se redondea hacia abajo al entero menor más cercano: la parte fraccionaria simplemente se descarta.
Pero es fácil imaginar una situación en la que un número fraccionario deba redondearse al entero más cercano en cualquier dirección o incluso redondearse hacia arriba. ¿Qué haces en este caso?
Para esto y para muchas situaciones similares, Java tiene la Math
clase, que tiene los métodos round()
, ceil()
y floor()
.
Math.round()
método
El Math.round()
método redondea un número al entero más cercano:
long x = Math.round(real_number)
Pero aquí hay otro matiz: este método devuelve un long
número entero (no un int
). Debido a que los números reales pueden ser muy grandes, los creadores de Java decidieron utilizar el tipo de entero más grande disponible en Java: long
.
En consecuencia, si un programador quiere asignar el resultado a una int
variable, debe indicar explícitamente al compilador que acepta la posible pérdida de datos (en el caso de que el número resultante no encaje en un int
tipo).
int x = (int) Math.round(real_number)
Ejemplos:
Declaración | Resultado |
---|---|
|
|
|
|
|
|
Math.ceil()
método
El Math.ceil()
método redondea un número a un entero. Aquí hay ejemplos:
Declaración | Resultado |
---|---|
|
|
|
|
|
|
Math.floor()
método
El Math.floor()
método redondea un número a un entero. Aquí hay ejemplos:
Declaración | Resultado |
---|---|
|
|
|
|
|
|
Por supuesto, al redondear un número a un número entero, es más fácil simplemente usar un operador de conversión de tipos:(int)
Declaración | Resultado |
---|---|
|
|
Si le resulta difícil recordar estos nombres, una breve lección de inglés le ayudará:
Math
significa matemáticasRound
significa redondoCeiling
significa techoFloor
significa piso
2. Cómo se estructuran los números de punto flotante
El double
tipo puede almacenar valores en el rango de a . Este amplio rango de valores (en comparación con el tipo) se explica por el hecho de que el tipo (así como ) tiene una estructura interna completamente diferente a los tipos enteros. Internamente, el tipo codifica su valor como dos números: el primero se llama mantisa y el segundo se llama exponente .-1.7*10308
+1.7*10308
int
double
float
double
Digamos que tenemos el número 123456789
y lo almacenamos como una double
variable. Cuando lo hacemos, el número se convierte en , e internamente el tipo almacena dos números: y . La mantisa ("parte significativa del número" o mantisa) se resalta en rojo, mientras que el exponente se resalta en azul.1.23456789*108
double
23456789
8
Este enfoque hace posible almacenar tanto números muy grandes como muy pequeños. Pero debido a que la representación del número está limitada a 8 bytes (64 bits) y algunos de los bits se usan para almacenar el exponente (así como el signo de la mantisa y el signo del exponente), el máximo de dígitos disponibles para representar la mantisa es 15 _
Esta es una descripción muy simplificada de cómo se estructuran los números reales.
3. Pérdida de precisión al trabajar con números reales
Cuando trabaje con números reales, siempre tenga en cuenta que los números reales no son exactos . Siempre puede haber errores de redondeo y errores de conversión al convertir de decimal a binario. Además, la fuente de error más común es la pérdida de precisión al sumar o restar números en escalas radicalmente diferentes.
Este último hecho es un poco alucinante para los programadores novatos.
Si restamos de , obtenemos .1/109
109
109
Restar números en escalas radicalmente diferentes | Explicación |
---|---|
|
El segundo número es extremadamente pequeño , lo que hará que su significado (resaltado en gris) sea ignorado. Los 15 dígitos significativos están resaltados en naranja. |
Qué podemos decir, programación no es lo mismo que matemáticas.
4. Trampa al comparar números reales
Otro peligro acecha a los programadores cuando comparan números reales. Surge cuando se trabaja con números reales, porque se pueden acumular errores de redondeo. El resultado es que hay situaciones en las que se espera que los números reales sean iguales, pero no lo son. O viceversa: se espera que los números sean diferentes, pero son iguales.
Ejemplo:
Declaración | Explicación |
---|---|
|
El valor de la variable a será 1000000000.0 El valor de la variable c será 1000000000.0 (el número en la b variable es demasiado pequeño) |
En el ejemplo anterior, a
y c
no deberían ser iguales, pero lo son.
O pongamos otro ejemplo:
Declaración | Explicación |
---|---|
|
El valor de la variable a será 1.0 El valor de la variable b será1.0 |
5. Un dato interesante sobrestrictfp
Java tiene una palabra clave especial (puntostrictfp
flotante estricto ) , que no se encuentra en otros lenguajes de programación . ¿Y sabes por qué lo necesitas? Empeora la precisión de las operaciones con números de coma flotante. Aquí está la historia de cómo llegó a ser:
GO TO FULL VERSION