Re: YA no se restar!

From: Date: Fri, 28 May 2004 08:02:04 +0000
Subject: Re: YA no se restar!
References: 1  Groups: php.general.es 
Request: Send a blank email to general-es+get-48992@lists.php.net to get a copy of this message
Es por una cuestión de que lo que a ti te parecen numeros redondos, para la CPU que trabaja en binario no lo son. Por eso, para transacciones monetarias existen los tipos de datos currency o money que trabajan con una cantidad limitada de decimales, para que no se acumulen errores de representación numérica. Es bastante habitual que si estás queriendo balancear unas operaciones contables trabajadas sobre variables de tipo numéricas de punto flotante, siempre te queden fracciones infimas de diferencia. Lo mejor sería que el lenguaje ofreciera variables con una cantidad fija de decimales, usualmente dos o tres decimales mas que la cantidad minima a representar, esto es, para importes con centimos, unos 4 o 5 decimales. De esta manera, el propio lenguaje trunca automaticamente esas fracciones sobrantes (imaginate, te esta dando diferencia en la 16a cifra decimal) Tienes otras dos posibilidades, ambas espantosas. Una es que trabajes con enteros, escalando las cifras 4 posiciones. La razon de usar dos o tres decimales por encima de los centimos es para que en operaciones de division, el resultado se pueda redondear en lugar de simplemente truncar. La otra alternativa es que uses la funcion de redondeo a dos decimales para aplicarle a los resultados de las operaciones: round($importe,2) Esta es la mejor de las dos. O sea, supon que estas contabilizando los intereses de unas cuentas de ahorro. Esta es una operacion que te va a dar siempre fracciones decimales bastante largas (salvo que, de casualidad, la tasa de interes nominal te de numeros redondos, lo cual es raro). Tras haber hecho el calculo,le haces el redondeo, y eso es lo que registras. Si no lo hicieras así, veras que muchas veces, los libros contables no te cierran pues el acumulado de los intereses pagados a los clientes no coincide con el total de intereses que sale de la cuenta del banco. Te pongo un ejemplo simple en decimal. Supon que calculaste que el interes devengado por un par de cuentas de ahorro ha sido de 0.3333333 que, cuando lo asientas en la base de datos, dado que usaste un campo de tipo numerico de dos decimales, queda registrado como 0.33. El acumulado de los intereses pagados en esas cuentas, que fuiste llevando en memoria, te da 0.666666666, con tantos decimales como PHP lleve. Cuando asientas este acumulado en los libros, el redondeo lo lleva a 0.67. Ahora vas a balancear los libros con una consulta de SQL, algo asi como Select sum(Debe), sum(Haber) from...... y el caso es que te da un centavo de diferencia. Los clientes recibieron 0.66 de intereses entre los dos, al banco le figura que pagó 0.67. Hace unos 30 años un programador de un banco fue acumulando en su cuenta las diferencias y se hizo una fortuna. Desde entonces existen normas para evitar estos 'errores'. Satyam ----- Original Message ----- From: "Innox - Juan Carlos Gonzalez" <jgonzalez@innox.com.mx> To: "phpes" <php-es@lists.php.net> Sent: Friday, May 28, 2004 1:12 AM Subject: [PHP-ES] YA no se restar! > > Jóvenes!! AYUDA!!! > > // código > echo "a = $a, b = $b\n"; > echo "resta = ".($a-$b); > > // resultado > a = -0.1, b = -0.1 > resta = 3.60822483003E-16 > > Yo se que es un problema común... también se que alguien ha tenido ese > problema y lo solucionó. > > GRACIAS! > > -- > Atentamente, > > Juan Carlos González > Innox - Innovación Inteligente > +52 (33) 3615 5348 > jcgonz@innox.com.mx > http://www.innox.com.mx > > -- > PHP Spanish Localization Talk Mailing List (http://www.php.net/) > To unsubscribe, visit: http://www.php.net/unsub.php > >

« previous php.general.es (#48992) next »