Aritmética Binaria y Decimal

Por Qué Nunca Usar float y double para Representar Montos de Dinero

Cuando aprendemos a programar una de las primeras lecciones es que se usan diferentes tipos de datos para representar números enteros y números no enteros. Una variable entera no puede tener el valor 0,5. En Pascal se usan los tipos Integer y Real y en C están por ejemplo los tipos int, long, float y double.

Supongamos que tenemos que hacer un sistema de permita administrar sumas de dinero; más específicamente, deudas y pagos. Puede ser para un banco, una tarjeta de crédito, un almacén o cualquier aplicación comercial. Para dicho sistema tenemos que hacer una función en C muy sencilla que reciba la deuda actual y un arreglo de pagos que realizó el deudor y que devuelva la deuda actualizada una vez descontados los pagos. Este podría ser el prototipo:

double actualizarDeuda(double deuda, double pagos[], int cantPagos);

Como la deuda puede ser con centavos, no podemos usar int para representarla entonces usamos double.

Lo que hace la función es restar de la deuda cada elemento del arreglo pagos y devolver el monto actualizado.

double actualizarDeuda(double deuda, double pagos[], int cantPagos){
    double deudaActualizada = deuda;
    int i;
    for(i = 0; i<cantPagos;i++){
        deudaActualizada -= pagos[i];
    }
    return deudaActualizada;
}

Vamos a constatar que la función hace lo esperado con una prueba.

Supongamos que un deudor tenía una deuda de $308,21 y realizó 4 pagos por $8,01; $0,20; $299,99 y $0,01. Si bien no es sencillo pagar en efectivo montos como $8,01, es un caso que puede darse perfectamente en transacciones electrónicas.

double deuda = 308.21d;
double pagos[4] = {8.01d, 0.20d, 299.99d, 0.01d};

En teoría la deuda está saldada así que la función debería devolvernos que la deuda es $0,00.

double miDeuda = actualizarDeuda(deuda, pagos, 4);
if(miDeuda == 0.0d){
    printf("Libre deuda.\n");
} else {
    printf("Al Veraz.\n");
}

Sin embargo la prueba imprime Al Veraz. es decir que nuestro sistema sigue registrando una deuda a pesar de que está saldada.

La nueva deuda no es $0,00, pero casi. El valor es $-0,00000000000000909516. Es decir, nuestra función nos calculó que el deudor pagó 9 milbillonésimas de peso más de lo que debía.

Esto nos hace pensar que hay un error de redondeo así que decidimos usar la función round.

miDeuda = round(actualizarDeuda(deuda, pagos, 4));
if(miDeuda == 0.0d){
    printf("Redondeando, logro el libre deuda.\n");
} else {
    printf("Redondeando, igual voy al Veraz.\n");
}

Ahora sí obtenemos el resultado Redondeando, logro el libre deuda lo que es en principio correcto.

A pesar de que en muchos sistemas el problema de la precisión está “solucionado” de esa manera, no se está atacando la causa del problema sino una de sus consecuencias. Como se observa a continuación, redondear el resultado puede llevarnos a dar por saldada una deuda que todavía no está totalmente paga.

pagos[2]-=0.4d;
miDeuda = round(actualizarDeuda(deuda, pagos, 4));
if(miDeuda == 0.0d){
    printf("Con redondeo, debiendo $0,40 igual logro el libre deuda.\n");
} else {
    printf("A pesar de redondear, como debo voy al Veraz.\n");
}

Si descontamos $0,40 de uno de los pagos, está claro que no deberíamos extender el libre deuda. Sin embargo, obtenemos el cartel Con redondeo, debiendo $0,40 igual logro el libre deuda lo que es incorrecto y le hace perder dinero quien nos encargó hacer el sistema. Es una situación complicada para nosotros ya que desde el punto de vista del acreedor, es una atrocidad.

Este problema lo tenemos en cualquier lenguaje de programación y también lo tenemos en muchas aplicaciones muy usadas para hacer cálculos con montos de dinero.

arit-excelLa única solución que ofrecen al problema en el caso de esa planilla de cálculo tan famosa es “redondear” (http://support.microsoft.com/kb/214118/es).

La causa del problema está en la representación binaria de los números de coma flotante. Como no todos los números son representables se tiene que buscar el número más cercano al especificado y eso implica un error en la representación. Por ejemplo el número 0,11 no es representable como double (porque en binario es periódico) y es aproximado con 0,11000000000000000056.

Los números de coma flotante están definidos por el estándar IEEE-754 que data de 1985. A partir de 2008, el estándar incorporó además de los números de binarios de coma flotante que ya existían (que usan base 2 como los float y double) nuevos números decimales de coma flotante (que usan base 10).

Esa es la solución al problema de la precisión que estamos teniendo. Vamos a reescribir la función de esta forma:

_Decimal64 actualizarDeuda(_Decimal64 deuda, _Decimal64 pagos[],int cantPagos){
    _Decimal64 deudaActualizada = deuda;
    int i;
    for(i = 0; i<cantPagos;i++){
        deudaActualizada -= pagos[i];
    }
    return deudaActualizada;
}

Usamos el tipo _Decimal64 en lugar de double. El resto es igual.

Y ahora sin aplicar ningún redondeo, las cuentas simplemente dan el resultado esperado.

_Decimal64 deuda = 308.21dd; 
/* el sufijo dd es el que corresponde al tipo _Decimal64 */
_Decimal64 pagos[4] = {8.01dd, 0.20dd, 299.99dd, 0.01dd};
_Decimal64 miDeuda = actualizarDeuda(deuda, pagos, 4);
if(miDeuda == 0.0dd){
    printf("Con _Decimal64, obtengo en libre deuda normalmente.\n");
} else {
    printf("Con _Decimal64, al Veraz.\n");
}

El soporte de decimales de coma flotante está disponible a partir de GCC 4.2, pero no está disponible para todas las plataformas. En particular en Windows con Cygwin obtenemos un error que dice “error: decimal floating point not supported for this target”.

Otros compiladores sí lo soportan en Windows como por ejemplo el de Intel. http://software.intel.com/en-us/articles/using-decimal-floating-point-with-intel-c-compiler/.

Más información

  1. http://en.wikipedia.org/wiki/IEEE_754-2008
  2. http://speleotrove.com/decimal/
Anuncios

¿Dónde es más barata la nafta, en Argentina o en Estados Unidos?

Lugar Impuesto USD mínimo (litro) USD máximo (litro) Neto USD mínimo Neto USD máximo
California USD 0,645 por galón $0,98 $1,38 $0,81 $1,21
Argentina 88,6794% (47% del precio final es impuesto) $1,43 $1,57 $0,76 $0,83
New York USD 0,634 por galón $1,01 $1,21 $0,85 $1,05
Florida USD 0,529 por galón $0,96 $1,58 $0,82 $1,44

Valores:

1 Dólar $4,36
1 US Gallon 3,785411784 litros
Premium “barata”
$6,25
Premium “cara” $6,84

En el primer cuadro se observa una comparación de los precios de la nafta “premium” a precios en dólares de hoy entre Argentina y tres lugares de Estados Unidos. En el segundo los valores tomados como parámetro. Esos tres lugares de EE.UU. no tienen los impuestos más baratos sino que están por encima del promedio, pero tienen mucha población así que son representativos.

El precio máximo de Estados Unidos es fiable (ver fuentes al final de estas líneas). Se ve en los listados que hay estaciones de servicio que cobran muy caro, por motivos particulares.

En cambio el precio caro en Argentina es relativo. Sé que se puede encontrar la nafta premium a más de $6,84 en algunos surtidores del país.

Dicho esto, se observa que en Argentina pagamos la nafta en el surtidor hasta un 40% más que en Estados Unidos. Aún tomando los precios más caros de EE.UU. todavía son menores a los nuestros.

Lo curioso es ver que, al descontar los impuestos, las petroleras en Argentina cobran como mínimo un 10% más barato el producto. Es decir que tenemos combustibles caros y baratos simultáneamente. Son baratos para quien nos los vende y caros para quienes los compramos. En definitiva el consumidor no se beneficia de los supuestos menores precios internos.

Es riesgoso que se fije un precio máximo para un producto ya que se incentiva la demanda y se desincentiva la oferta ocasionando que falte producto. Si la nafta premium que es la más cara está “barata”, entonces la súper que se consigue aún a menos precio podría estar “regalada” lo que explicaría que a veces haya cola en los surtidores y que en algunos lugares sea muy difícil de conseguir, sobre todo de la marca que la vende mas barata.

No hay que olvidar las diferencias de impuestos al comparar los precios. A veces pensamos que las empresas nos cobran más caro que en otros lugares, pero en verdad son los impuestos los culpables de tal diferencia.

Fuentes:

1. Precios en surtidores (hay gran variación entre máximo y mínimo)

2. Impuestos argentinos

3. Impuestos en USA al 2009 según el estado (en centavos por galón)

Tabla Histórica Apertura 2004 – Apertura 2010

Equipo Máx Min Tít. Prom. A 04
C 05
A 05
C 06
A 06
C 07
A 07
C 08
A 08
C 09
A 09
C 10
A 10
Estudiantes 9 1 2 4,15 30 4 31 4 28 5 24 9 44 1 37 3 30 5 39 2 28 5 29 5 31 8 40 2 45 1
Boca 12 1 3 5,46 26 7 22 12 40 1 43 1 44 1 39 2 31 3 39 2 39 1 22 10 27 10 20 12 25 9
Vélez 8 1 2 4,92 34 2 39 1 33 3 25 8 30 7 26 8 27 8 32 5 26 8 40 1 34 3 27 8 43 2
Lanús 12 1 1 6,00 26 7 28 7 23 12 35 2 31 6 28 6 38 1 18 12 37 3 38 2 31 8 29 6 28 6
San Lorenzo 12 1 1 6,46 30 4 22 12 28 5 28 7 28 8 45 1 29 6 35 4 39 1 24 8 32 6 20 12 24 10
River 14 1 1 6,62 33 3 27 8 28 5 34 3 38 3 33 4 23 12 43 1 14 14 27 7 21 12 22 10 31 4
Banfield 12 1 1 6,92 26 7 33 2 28 5 31 5 20 11 19 12 32 2 22 11 23 9 23 9 41 1 32 4 20 12
Newell’s 14 1 1 7,85 36 1 24 11 20 14 31 5 16 14 19 12 27 8 29 8 31 4 21 11 39 2 30 5 26 7
Independiente 14 3 0 8,23 23 13 26 9 32 4 23 10 32 4 25 10 28 7 31 6 18 13 21 11 34 3 34 3 14 14
Argentinos 14 1 1 8,69 22 14 21 14 28 5 22 11 20 11 26 8 31 3 30 7 23 9 15 14 32 6 41 1 24 10
Arsenal 14 3 0 8,77 24 12 30 5 22 13 22 11 32 4 30 5 26 10 25 9 28 5 18 13 27 10 19 14 32 3
Colón 13 3 0 8,69 27 6 26 9 26 10 20 13 18 13 28 6 22 13 23 10 23 9 34 3 34 3 21 11 26 7
Racing 14 3 0 9,23 26 7 32 3 25 11 19 14 26 9 23 11 25 11 15 14 22 12 30 4 17 13 29 6 29 5
Gimnasia 14 2 0 9,46 25 11 29 6 37 2 32 4 23 10 17 14 19 14 17 13 27 7 28 6 13 14 24 9 15 13

La tabla muestra los puntos y la posición de cada equipo en los últimos 13 torneos. Está ordenada por sumatoria de puntos. Sólo aparecen los equipos que jugaron los 13 torneos.

  • Máx: la peor ubicación del equipo.
  • Mín: la mejor ubicación.
  • Tít.: la cantidad de veces que ganó el capeonato. Salir primero no implica ganar el campeonato, ya que puede haber empate en el primer puesto, pero sólo uno gana el campeonato.
  • Prom.: la posición promedio.

Como se ve, Boca es el que ganó más torneos, pero tiene menos puntos acumulados que Estudiantes. Tiene más puntos que Vélez, pero una peor ubicación promedio a lo largo de los 13 torneos.

Estudiantes tiene la mejor ubicación promedio, la mayor cantidad de puntos y nunca bajó del noveno puesto. Esta tabla no abarca sólo la “era Verón”, ya que hasta el Clausura 2006 inclusive, la Brujita no jugaba en Estudiantes.

Promedio de las Últimas 6 Temporadas

El promedio de puntos de las últimas 6 temporadas actualizado a la sexta fecha del Apertura 2009.  Coincide con los mejores años de Estudiantes (desde la llegada de Merlo al campeonato Apertura 2006 y la Copa Libertadores 2009).

Racing es el peor equipo de los que jugaron las 6 temporadas y Boca el mejor, con máximo puntaje en 3 temporadas consecutivas (entre 2005 y 2008).

Pos. Equipo Temporada 2004 / 2005 Temporada 2005 / 2006 Temporada 2006 / 2007 Temporada 2007 / 2008 Temporada 2008 / 2009 Temporada 2009 / 2010 Temporadas en Primera Total Prom.
1 Boca 48/38 83/38 83/38 70/38 61/38 5/6 6 350/196 1,786
2 Estudiantes 61/38 52/38 81/38 69/38 57/38 16/6 6 336/196 1,714
3 Vélez 73/38 58/38 56/38 59/38 66/38 14/6 6 326/196 1,663
4 San Lorenzo 52/38 56/38 73/38 64/38 63/38 10/6 6 318/196 1,622
5 Lanús 54/38 58/38 59/38 56/38 75/38 5/6 6 307/196 1,566
6 River 60/38 62/38 71/38 66/38 41/38 5/6 6 305/196 1,556
7 Banfield 59/38 59/38 39/38 54/38 46/38 14/6 6 271/196 1,383
8 Independiente 49/38 55/38 57/38 59/38 39/38 10/6 6 269/196 1,372
9 Arsenal 54/38 44/38 62/38 51/38 46/38 7/6 6 264/196 1,347
10 Newell’s 60/38 51/38 35/38 56/38 52/38 10/6 6 264/196 1,347
11 Gimnasia 54/38 69/38 40/38 36/38 55/38 5/6 6 259/196 1,321
12 Colón 53/38 46/38 46/38 45/38 57/38 11/6 6 258/196 1,316
13 Rosario Central 61/38 45/38 52/38 41/38 40/38 13/6 6 252/196 1,286
14 Argentinos 43/38 50/38 46/38 61/38 38/38 12/6 6 250/196 1,276
15 Racing 58/38 44/38 49/38 40/38 52/38 4/6 6 247/196 1,260
16 Gimnasia (J) 0/0 51/38 43/38 35/38 38/38 0/0 4 167/152 1,099
17 Tigre 0/0 0/0 0/0 56/38 62/38 3/6 3 121/82 1,476
18 Huracán 0/0 0/0 0/0 52/38 58/38 1/6 3 111/82 1,354
19 Godoy Cruz 0/0 0/0 42/38 0/0 49/38 8/6 3 99/82 1,207
20 Olimpo 43/38 49/38 0/0 42/38 0/0 0/0 3 134/114 1,175
21 Quilmes 44/38 39/38 21/38 0/0 0/0 0/0 3 104/114 0,912
22 Instituto 42/38 28/38 0/0 0/0 0/0 0/0 2 70/76 0,921
23 Atlético Tucumán 0/0 0/0 0/0 0/0 0/0 7/6 1 7/6 1,167
24 Nueva Chicago 0/0 0/0 43/38 0/0 0/0 0/0 1 43/38 1,132
25 Belgrano 0/0 0/0 41/38 0/0 0/0 0/0 1 41/38 1,079
26 San Martín (T.) 0/0 0/0 0/0 0/0 40/38 0/0 1 40/38 1,053
27 Almagro 38/38 0/0 0/0 0/0 0/0 0/0 1 38/38 1,000
28 San Martín (S. J.) 0/0 0/0 0/0 35/38 0/0 0/0 1 35/38 0,921
29 Tiro Federal 0/0 27/38 0/0 0/0 0/0 0/0 1 27/38 0,711
30 Chacarita 0/0 0/0 0/0 0/0 0/0 3/6 1 3/6 0,500
31 Huracán (TA) 17/38 0/0 0/0 0/0 0/0 0/0 1 17/38 0,447

No Maten al CD de Audio

Cada día se oyen más voces indicando que la calidad del compact disc no es suficiente. Que dieciséis bits no son suficientes para capturar la calidad musical, que las frecuencias altas se pierden, que la música es analógica y todo lo digital siempre será una aproximación, pero jamás podrá igualarla.

Son todos mitos sin fundamento originados en la ignorancia y que en gran medida son fogoneados por la industria discográfica que quiere justificar los nuevos formatos para audiófilos (SACD y DVD-Audio).

Las Frecuencias Altas

No hay evidencia científica (hasta ahora) de que el ultrasonido (aquellas frecuencias por sobre los 20.000 Hz) afecten en algo a las frecuencias inferiores. Más bien hay bastante evidencia de que no tienen el menor valor. Pero ¿hasta qué frecuencia se puede almacenar en un CD? Mucho más de lo que el mejor oído humano puede percibir: 22.050 Hz.

El Mundo el Analógico y Lo Digital es Sólo una Aproximación

Este es el argumento más fácil de rebatir y es sin duda fruto de la ignorancia y de un prejuicio contra lo digital. Está claro que toda grabación analógica o digital será una aproximación al original, ya que aún no se inventó una forma de meter una orquesta adentro de una caja y hacerlos tocar cuando queramos. Pero más allá de eso, existe el llamado teorema del muestreo, que demuestra que la reconstrucción exacta de una señal periódica continua en banda base a partir de sus muestras es matemáticamente posible si la señal está limitada en banda y la tasa de muestreo es superior al doble de su ancho de banda. (fuente).

Esto significa que en teoría se puede reconstruir la onda original del sonido en forma exacta a partir de las muestras siempre y cuando se hayan tomado esas muestras al doble de la frecuencia más alta. En el caso del sonido la frecuencia más alta relevante es alguna que esté por sobre el umbral de percepción del oído humano. Como la frecuencia de muestreo en los CDs de audio es 44.100 Hz, estamos pudiendo reconstruir el sonido hasta su frecuencia 22.050 Hz.

Los valores de la onda intermedios entre muestra y muestra se obtienen a partir de una fórmula matemática expresada en el teorema de muestreo y es exactamente lo que hacen los conversores digital-analógico de cualquier computadora o equipo de música. Esos valores no son una aproximación lineal, sino el valor real que tenía la onda en ese punto.

Donde hay una pérdida es al almacenar los valores de esas muestras como dígitos. Es decir, el teorema requiere que los valores de las muestras sean exactos. Al almacenar esos valores como números hay una pérdida de exactitud. Esa pérdida se llama ruido de cuantificación y va de la mano con la cantidad de bits que se usen para cada muestra.

16 bits vs. 24 bits

Los CDs de audio usan 16 bits para cada muestra de la onda (16 bits para cada canal), está establecido que el ruido de cuantificación que ello implica está muy, pero muy por debajo del umbral de percepción del oído humano y por sobre la mayoría de los equipos de música hogareños (ver los vínculos a más información al final de este texto). Además se han hecho pruebas de audición donde a la gente se le hacía escuchar un misma grabación en 16 y 24 bits sin decirles cuál era cuál y resultaron indistinguibles. En grabaciones de estudio sí se utilizan 24 bits, simplemente para permitir aplicar efectos y hacer mezclas de pistas evitando que el ruido de cada pista se sume tan rápidamente al aplicar cada efecto. Eso es lo mismo que hace cualquier contador al redondear los decimales solo en el resultado final y no cada resultado parcial, para mantener mejor precisión. De hecho, por el ruido inherente de la señal analógica que se está digitalizando, aun en el ambiente controlado de un estudio y con equipamiento muy moderno, se sabe que los últimos 4 bits de los 24 son aleatorios (puro ruido). Esto se debe a que los micrófonos aportan ruido térmico entre otros factores.

Quienes defienden los medios analógicos para almacenar música (léase vinilos) están omitiendo que un grano de polvo en el surco del vinilo implica muchísimo más ruido que cualquier ruido de cuantificación que pueda haber en un CD. Además de que ningún medio analógico puede superar la relación señal ruido del CD de audio.

El potencial de calidad de audio del compact disc (suponiendo que no se cometió ningún error u omisión en su grabación y masterización cosa que es bastante habitual) es probablemente tan alto como es necesario. En lugar de buscar nuevos formatos con más bits o más muestras por segundo, ¿por qué no nos concentramos en hacer que más y mejor música llegue a oídos de más gente? Mejor gastemos más en mejores parlantes.

El formato DVD-Audio, su competidor el SACD y los sitios de Internet que venden música en 24 bits y 192 kHz no tienen una justificación desde el punto de vista de la calidad de sonido por sobre el CD de audio.

Más información

Venta de Entradas 1991 – 2004

En un blog de Estudiantes leí un comentario que hacía referencia a un artículo del diario La Nueva Provincia del 2005 en el que se pueden leer los datos de venta de entradas (plateas y generales) de todos los clubes fútbol argentino para cada torneo entre 1991 y 2004. Se basa en los datos oficiales de la AFA.

La comparación entre Gimnasia y Estudiantes así como la de Boca con River y la de Racing con Independiente, por dar ejemplos, es lo primero que uno intenta hacer.

Evolución de Venta de Entradas 1991 - 2004

Evolución de entradas vendidas entre 1991 y 2004 por Estudiantes y Gimnasia.

  • No hay datos de Estudiantes mientras estuvo jugando el Campeonato Nacional B entre fines de 1994 y principios de 1995.
  • En los torneos en los que ambos equipos estaban en la A Gimnasia superó en cantidad de público en 8 torneos. En el resto (16) Estudiantes vendió más entradas.

Vamos a los números por torneo.

  • Gimnasia. Esperanza Media (promedio): 100.530. Desvío estándar: 29.190.
  • Estudiantes. Esperanza Media (promedio): 112.327. Desvío estándar: 26.696.

Estadísticamente Estudiantes tiene mejor esperanza, menos variación y mayor valor total. En el artículo están los datos detallados de todos los clubes de primera.

Promedios 2009 – 2010

Así arrancan los promedios del descenso para la temporada 2009 – 2010 del fútbol argentino.

Promedios Temporada 2009 - 2010

Promedios Temporada 2009 - 2010

Además de los recién ascendidos, Rosario Central, Gimnasia y Esgrima La Plata y Racing Club son los más comprometidos. Argentinos, Independiente y River tienen que hacer muchos puntos para no sufrir en la siguiente temporada (2010-2011).