Una de las cosas que siempre pasamos por alto, es realizar las típicas operaciones aritméticas sin pensar demasiado en como los compiladores o interpretadores lo realizan.
Por ejemplo, podemos comprobar como correcta la siguiente ecuación:
(int) ( (0.7 + 0.1) * 10 ) = (0.7 + 0.1) * 10
Como bien sabemos todos, (int), es una forma de obtener el Entero de un número. Otro aspecto interesante es su velocidad, ya que en muchos lenguajes, es un constructor de los mismos, es decir es un rasgo nativo del ellos y ahí radica la razón de su performance.
Casi siempre, por no decir siempre, cuando hago esta pregunta a un idóneo-programador-desarrollador-analista-ingeniero-etc. me responde que SI es correcta la ecuación. Confieso ser de ellos … al ver la primera vez dicha ecuación dije 8 = 8. Los aliento a probarla en cualquier lenguaje que utilicen.
Como todos sabemos, los decimales son en si fracciones:
0.3333333333…3…3 = 1/3
El sistema decimal, es decir el sistema con base 10, que utilizamos para los sistemas financieros/contables, nos dice esto último: “un tercio de Uno es un cero seguido por una coma y que termina en infinitos Tres. Si en cambio utilizamos un sistema base 3, un tercio de Uno sería 0.1 y ciertamente sería mucho mas preciso.
En los sistemas binarios, base 2, así como lo es el base 10 y todos los demás, pueden existir sesgos en la exactitud.
Y lo cierto es que nuestros equipos/sistemas/lenguajes no pueden manejar la idea de infinitos de forma tan natural como lo hace un alumno del primario. Tienen un límite. Los lenguajes que se usan desde hace casi una década y dominan los sistemas a nivel mundial, solo manejan hasta una cantidad determinada de decimales.
Una de las cosas que me interesan más, es hacer bien lo que se supone se debe hacer bien. Es decir, que si sabemos sumar, sepamos sumar.
En PHP4/5/x, y otro lenguajes no tipados, parece que no hay mucho problema al inicio ya que no nos piden declarar el tipo de variables a utilizar. Sin embargo en JAVA, desde un inicio, nos dan la idea de los límites de nuestra realidad; según el estándar internacional IEEE 754, Double junto a Float, son los tipos de punto flotante ( los que tienen comas 🙂 ), siendo el primero de precisión doble (64bit) y el segundo simple (32bit). A primera vista Double, nos parece que nos basta y sobra.
Sin embargo, Double, puede traernos algunos dolores de cabeza con simples sistemas de reportes, contables, o de sumas. Por ejemplo, tomar un valor de una celda de una planilla de calculo como 1261.49, en Double puede representar:
1261.490000000000009094947017729282379150390625
new Double( ( (0.7) + (0.1) ) * 10 );
7.999999999999999
- BigDecimal
- DecimalFormat
- String.format()
Con BigDecimal, resolvemos este inconveniente.
BigDecimal alfa = new BigDecimal(“0.5”);
BigDecimal beta = new BigDecimal(“0.1”);
BigDecimal resultado = alfa.add(beta); // retorna un 0.6 exacto
Con String.format(), se puede ver de esta otra forma :
- String.format(“%.2f”, 3.1499) // retorna “3.14”
- String.format(“%.3f”, 3.1499) // retorna “3.140”
- String.format(“%.2f”, 3.1) // retorna “3.10”