[pyar] Valores incorrectos
Pablo Ziliani
pablo en kultroom.com
Vie Oct 15 19:13:56 ART 2010
Diego E. Ahumada wrote:
>
> 2010/10/15 Cristian Segura <ska.python en gmail.com
> <mailto:ska.python en gmail.com>>
>
> Buenas chicos, mi primer duda a la lista :P
>
> Estaba resolviendo un ejercicio, y me surgió un problema. El
> ejercicio en cuestión es el siguiente:
>
> "Dada una cantidad de dinero, indicar como repartir el vuelto de
> manera que se utilice la menor cantidad de monedas"
>
> El código que tengo es el siguiente:
>
> b = (100, 50, 20, 10, 5, 2, 1, .5, .25, .1, .05)
>
> v = float(raw_input("Ingrese vuelto: "))
> i = 0
> j = 0
> l = len(b)
>
> while i != l:
> while v - b[i] >= 0:
> v -= b[i]
> j += 1
> if j != 0:
> print j, " billetes/monedas de ", b[i]
> print "El valor restante es: ", v # Esta unicamente
> para comprobar los resultados
> j = 0
> i += 1
>
> La salida del script utilizando como valor 1807.35 es:
>
> 18 billetes/monedas de 100
> El valor restante es: 7.35
> 1 billetes/monedas de 5
> El valor restante es: 2.35
> 1 billetes/monedas de 2
> El valor restante es: 0.35
> 1 billetes/monedas de 0.25
> El valor restante es: 0.0999999999999
> 1 billetes/monedas de 0.05
> El valor restante es: 0.0499999999999
>
> Mi pregunta es, por que al hacer la resta 0.35-0.25 devuelve 0.09
> y no 0.1?
>
> Un saludo y gracias
>
>
> El problema se debe a cómo python y las computadoras en general
> manejan los números de coma flotante. La respuesta precisa la
> encontrás en: http://docs.python.org/tutorial/floatingpoint.html
Por cierto, el módulo Decimal fue hecho (entre otros) por Facundo
Batista, uno de los creadores de PyAr. Muy probablemente también él haya
escrito o ayudado a escribir ese artículo.
> Las alternativas son utilizar el módulo 'decimal' (from decimal import *),
Es mejor hacer "from decimal import Decimal". Importar con asterisco
está fuertemente desaconsejado.
> o hacer, por ejemplo, round(3.5-2.5,2).
Yo estoy lejos de conocer los detalles, pero redondear es cambiar el
tipo de problema, no solucionarlo. De todas maneras ojo, en tu ejemplo
no hay "ganancia":
>>> round(3.5 - 2.5, 2)
1.0
>>> 3.5 - 2.5
1.0
Tampoco la habría con un número no redondo:
>>> 3.4 - 2.5
0.89999999999999991
>>> round(3.4 - 2.5, 2)
0.90000000000000002
>>> round(0.9, 2)
0.90000000000000002
>>> 0.9
0.90000000000000002
¿cuál es mejor?
Podés manejar más precisión (agregar decimales) y truncar el resultado
AL FINAL de la operación, pero siempre vas a tener algún grado de error
de redondeo. Hay mucha literatura al respecto.
Como regla de oro, si es plata (o cualquier cosa donde los decimales
sean críticos), usá Decimal. Decimal se basa en la representación visual
del número (que es la que usamos los humanos) y no en la cantidad de
bits que maneja el silicio por el que transita, por eso se crea a partir
de una string y no un float.
More information about the pyar
mailing list