Título: Ayuda en C que estoy reloco Publicado por: Fumoffuw en 27 Mayo 2015, 05:36 am Hola amigos, tengo un ejercicio que tengo que sacar la cantidad de billetes de 200 100 50 20 10 5 2 1 y luego las monedas de 0.50, 0.10 y 0.05
Este es lo que he hecho en C aunque falta pulir un poco agregando algunos ifs Código
El problema esta al final en la parte de los decimales (las monedas); si por ejemplo de entrada pongo el número 11.55 de salida me da los valores correctos en la parte de las monedas. Pero si por ejemplo pongo otro numero por ejemplo 1.55 u algun otro numero siempre me da salidas incorrectas y no entiendo porqué. Si alguien me da una mano lo agradeceria bastante que le he estado dando muchas vueltas en la parte de las monedas. Mod: Lod códigos deben ir en etiquetas GeSHi Título: Re: Ayuda en C que estoy reloco Publicado por: engel lex en 27 Mayo 2015, 05:55 am creo... que es un problema de precisión... su usas el debugger de tu ide lo verás...
lo que debes hacer es usar double en lugar de float y la lectura la haces con "%lf" en lugar de "%f" Título: Re: Ayuda en C que estoy reloco Publicado por: Fumoffuw en 27 Mayo 2015, 06:25 am Amigo eres un genio!
En la parte de Código
cambie float a double y %f a %lf y si me dió los resultados correctos(con el numero 1.55), pero cuando intenté con otros numeros todavia me salen errores. No tenia mucha idea de eso de la presicion ya que llevo unos 2 meses estudiando y solo me dediqué a estudiar los algoritmos y el lenguaje en si. Alguna manera de arreglar para que me acepten la mayoria de numeros posibles? Título: Re: Ayuda en C que estoy reloco Publicado por: engel lex en 27 Mayo 2015, 06:33 am el problema con los numeros flotantes es que ellos están representados como
(-1)s * c * be donde s es 1 bit para el signo, c es el coeficiente, b es la base y e el exponente en decimal es una nomenclatura cientifica normal (-1)0*123*10-1 tambien se puede leer como 123x10e-1 que sería 1,23 esto normalmente en programación está en binario (base 2) y para float (32bit) son 24 bits para coeficiente y 6 bits de exponente si no me equivoco (siempre es uno para signo)... así que el numero puede no ser siempre exacto... con double este rango se agranda a 64 bits, 53 para cociente, 10 para exponente y 1 para signo (creo que es así, no recuerdo exactamente), lo que da numeros de "doble precisión" ahora dime con cuales numeros falla? sabes usar el debugger de tu ide? (por el conio.h creo que debe ser dev c++) Título: Re: Ayuda en C que estoy reloco Publicado por: Fumoffuw en 27 Mayo 2015, 06:47 am He probado con bastantes numeros y la gran mayoria falla en la ultima parte que es la de 0.05
Si pongo numeros como 76.35 , 123.75 ,35,25 no me cuenta la parte de 005 me sale "La cantidad de monedas de 0.05 es : 0 " Pero algo curioso si pongo 123.15 (que se parece bastante a 123.75) me sale : "La cantidad de monedas de 0.05 es : 1 " Yo uso el codeblocks y no uso debugger, aunque tengo una idea vaga de que es eso. Título: Re: Ayuda en C que estoy reloco Publicado por: engel lex en 27 Mayo 2015, 07:17 am una solución que no quería tocar por ser un poco chapuzera pero puede arreglar el problema es bajar la presición del calculo... es decir...
en lugar de Código
hacemos Código
de resto ahorita estoy muy oxidado en c (ando pendiente de muchas cosas ahorita) y no sabría como resolver por cierto, el debug es algu muy simple pero util para programar... en code blocks sería, vas a la pestaña debug, y le das click en debug project (o similar), allí arrancará el programa, pero no hará nada, verás en el editor como la primera linea de ti main estará resaltada de un color, esa es la linea que se va a ejecutar a continuacion, deben tener unos botones para avanzar paso a paso, saltar, etc... busca la ventana "watches" o "variables" para ver las variables del programa en tiempo real para más info seguro en youtube hay bastante al respecto :P Título: Re: Ayuda en C que estoy reloco Publicado por: Peregring-lk en 27 Mayo 2015, 23:16 pm Cuando tú trabajas con números de precisión flotante, tienes que tener en cuenta bastantes cosas, pero por norma general, es como dice engel lex, problemas de precisión. Ejemplo bastante ilustrador:
Código Verás que imprime 0.5 sin problemas. Pero ahora, incrementale la precisión de impresión: Código Ahora hemos imprimido 0.5 con una precisión de 20 cifras decimales, y seguramente verás un valor como: 0.05000000000000000278. Es decir, en realidad `0.5` representa a un número un poquito más grande, ya que es imposible garantizar precisión exácta cuando se tratan de números flotantes (verás, de todas formas, que el error es muy muy muy pequeño). Pues eso es fundamentalmente lo que te está pasando, que esas diferencias de precisión te están jugando una mala pasada. En el caso concreto de 1.55, si imprimes el valor que `scanf` ha leído: Código
Te imprimirá algo como: 1.54999995231628417969 (un valor ligeramente menor a 1.55; y por eso te devuelve 0 en la última división). Incrementar la precisión ayuda, pero no resuelve el problema: Código
Ahora a mí me imprime algo como: 1.55000000000000004441 (un número ligeramente superior). Pero como verás, sigue sin ser exáctamente el mismo número. Por otro lado, en ésta división (supón que `n` es `float` como en tu caso original): Código
Si escribes un "literal de número flotante", como `0.50`, por defecto, dicho literal `0.50` tiene tipo `double`. Por tanto, `n` se transforma en un `double` antes de hacer la división. Luego, se hace una división entre `double`s y se transforma el valor en un entero para asignarlo a `b05`. Para realizar una división `float` y no `double`, debes especificar que tu literal lo es: `0.50f`, y así no habrá conversiones de `n`. Ésta conversiones implícitas puede incrementar (¡o disminuir, no se sabe!) la precisión, añadiendo más caos al asunto. Si la precisión es fija, trabaja con números enteros y te quitas de en medio a los flotantes, tal y como propuso engel lex: Código
O, para rematar la faena, hazlo con un bucle: Código
Explicación de mi `printf`: Si yo en el `printf` pusiera algo como: "%f" sin más, se mostraría en la salida algo como: Código
Por que por defecto, la precisión de un `printf` es de 6 cifras decimales. Para "personalizar" la precisión, existe el modificar `.*` que permite pasarle la precisión como parámetro, antes del número que quiero imprimir. Por ese motivo, he creado otro vector, llamado `prec`, que indica la precisión que quiero para cada elemento de la lista (ninguna para los números mayores a 0.5, de 1 cifra para 0.5 y 0.1, y de dos para 0.05), y ya se imprime bonito: Código
Título: Re: Ayuda en C que estoy reloco Publicado por: Fumoffuw en 28 Mayo 2015, 08:36 am Muchas gracias a los dos por responder, yo me acuerdo que leí eso de las precisiones (no me acuerdo de donde la verdad) pero no le tomé mucha importancia, ahora veo que si importa ;D
Yo estudio C de un libro que se llama "Programacion en C" de Luis Joyanes e Ignazion Zahonero que el profesor de la facultad nos dijo que lo compremos,en el índice busqué sobre la precision pero no lo encontré, la verdad es que el libro no me gusta mucho, siento que no da las ideas tan claras. Me recomendarian algun libro o de algún lugar para repasar estas partes teóricas lo agradecería bastante Título: Re: Ayuda en C que estoy reloco Publicado por: Peregring-lk en 28 Mayo 2015, 14:11 pm
Hay tantas situaciones que no creo que exista ningún libro lo suficientemente bueno, y para los detalles "de nivel medio", cualquiera te puede valer. Lo más importante es saber "qué está pasando" en tu programa, y conocer bien `printf` es un buen comienzo, así que repasa todas sus opciones con detalle. ¡O utilizar un debuggeador como `gdb`! |