1. Redondeo de números reales

Como ya hemos discutido, cuando se asigna un número real a una intvariable, 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 Mathclase, 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 longnú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 intvariable, 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 inttipo).

int x = (int) Math.round(real_number)

Ejemplos:

Declaración Resultado
int x = (int) Math.round(4.1);
4
int x = (int) Math.round(4.5);
5
int x = (int) Math.round(4.9);
5

Math.ceil()método

El Math.ceil()método redondea un número a un entero. Aquí hay ejemplos:

Declaración Resultado
int x = (int) Math.ceil(4.1);
5
int x = (int) Math.ceil(4.5);
5
int x = (int) Math.ceil(4.9);
5

Math.floor()método

El Math.floor()método redondea un número a un entero. Aquí hay ejemplos:

Declaración Resultado
int x = (int) Math.floor(4.1);
4
int x = (int) Math.floor(4.5);
4
int x = (int) Math.floor(4.9);
4

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
int x = (int) 4.9
4

Si le resulta difícil recordar estos nombres, una breve lección de inglés le ayudará:

  • Mathsignifica matemáticas
  • Roundsignifica redondo
  • Ceilingsignifica techo
  • Floorsignifica piso

2. Cómo se estructuran los números de punto flotante

El doubletipo 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*10308intdoublefloatdouble

Digamos que tenemos el número 123456789y lo almacenamos como una doublevariable. 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*108double234567898

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/109109109

Restar números en escalas radicalmente diferentes Explicación
1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
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
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
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, ay cno deberían ser iguales, pero lo son.

O pongamos otro ejemplo:

Declaración Explicación
double a = 1.00000000000000001;
double b = 1.00000000000000002;
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:

Los creadores de Java:
Realmente queremos que Java sea súper popular y ejecutar programas Java en tantos dispositivos como sea posible. ¡Así que nos aseguramos de que la especificación para la máquina Java diga que todos los programas deben ejecutarse de la misma manera en todos los tipos de dispositivos!
Fabricantes de procesadores Intel:
¡Hola a todos! Hemos mejorado nuestros procesadores y ahora todos los números reales se representan usando 10 bytes en lugar de 8 bytes dentro de nuestros procesadores. Más bytes significa más dígitos significativos. ¿Qué significa eso? ¡Así es! ¡Ahora tus cálculos científicos serán aún más precisos!
Científicos y todos los involucrados en cálculos ultraprecisos:
¡Fresco! Bien hecho. ¡Noticias excelentes!
Los creadores de Java:
¡No-no-no, chicos! Ya te dijimos que todos los programas Java deben ejecutarse igual en todos los dispositivos . Vamos a deshabilitar por la fuerza la capacidad de usar números reales de 10 bytes dentro de los procesadores Intel.
Ahora todo está bien de nuevo! No nos agradezcas.
Científicos y todos los involucrados en cálculos ultraprecisos:
¿Te has vuelto completamente loco? ¡Recupere rápidamente todo como estaba!
Los creadores de Java:
¡Chicos, esto es por vuestro bien! Imagínese: todos los programas Java se ejecutan de la misma manera en todos los dispositivos . ¡Eso es tan cool!
Científicos y todos los involucrados en cálculos ultraprecisos:
No. No es genial en absoluto. ¡Rápidamente pon todo de nuevo como estaba! ¿O sabes dónde pondremos tu Java?
Los creadores de Java:
Mmm. ¿Por qué no lo dijiste de inmediato? Por supuesto, lo volveremos a poner.
Restauramos su capacidad de usar todas las funciones de los procesadores más recientes.
Por cierto... También agregamos especialmente la strictfppalabra clave al idioma. Si lo escribe antes del nombre de una función, ¡entonces todas las operaciones que involucren números reales dentro de esa función serán igualmente malas en todos los dispositivos !