Decimal vs. Binario


Día a día veo cómo los informáticos seguimos tropezándonos con la misma piedra. Usar números de coma flotante para representar montos de dinero es incorrecto.

Veamos por qué.

1) Los números de coma flotante (de 16, 32, 64 u 80 bits) no pueden representar todos los valores dentro de su rango. Cuando se topan con un valor de esos, lo reemplazan por el más cercano. Es ahí cuando vemos números como 1.000000000000001 ó 3,66666666666667 cuando en realidad queremos 1 y 3,666666666666666.

2) Ese mínimo error de representación se va acumulando a medida que hacemos operaciones como sumas, multiplicaciones, etc. y terminan cambiando un monto de $10 por $10,01 o $9,99.

3) Ese centavito perdido no se hubiera perdido si hubiéramos hecho la cuenta como nos enseñaron en la escuela. Es un error que puede ser subsanado.

4) El problema es que para dinero una diferencia de $0,000000000001 es insignificante, pero no debemos permitir que esas diferencias se vayan acumulando y terminen generando diferencias de $1 o mayores.

La solución existe desde que se hizo el primer sistema que calculaba sumas de dinero, probablemente en COBOL, pero asombrosamente aún hoy sigue habiendo profesionales que definen montos de dinero como float o double.

La aritmética decimal precisa es la respuesta. En lugar de representar los números en binario de coma flotante, los representamos en decimal y en lugar de usar la unidad de coma flotante (muy veloz) presente en los procesadores desde el Intel 386, hacemos las cuentas con rutinas comunes, en general en lenguaje de alto nivel.

La ventaja, obviamente, es que tenemos el control sobre cómo queremos redondear en cada operación. Así cuando calculamos 1/3, podemos decidir si queremos 1, 2, 3 o 200 lugares después de la coma, pero jamás tendremos 0,3333333334, sino 0,333333333 o 0,33333333333333333333333333333. La longitud es arbitraria. Por ejemplo en Java, un BigDecimal puede tener como 2.000 millones de lugares después de la coma. En una base de datos como Oracle, tenemos un límite menor, pero generoso: algo así como 24 lugares.

En conclusión, para montos de dinero, jamás defina sus variables ni como float, ni double, ni single, ni extended. Use Numeric, Decimal, Digits, BigDecimal, etc. según su lenguaje o base de datos le provea.

Y tenga cuidado con MySQL si no usa la versión 5.1 o superior y el modo estricto, ya que por más que defina un Decimal, las cuentas las estará haciendo en coma flotante.

Anuncios

4 pensamientos en “Decimal vs. Binario

  1. Estoy haciendo una pequeña aplicación y estoy utilizando C. Estaba realizando cálculos con floats y me daban problemas. ¿Qué tipo de datos podría utilizar para este lenguaje?

    Muchas gracias

  2. El problema es que hago cálculos con euros y me aparecen decimales raros….

  3. Pingback: Excel no usa aritmética decimal « Ignorante

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s