• Jueves 25 de Abril de 2024, 10:54

Autor Tema:  No encuentro mi error (Solucionado)  (Leído 2060 veces)

portirijillo

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
No encuentro mi error (Solucionado)
« en: Sábado 17 de Septiembre de 2011, 22:51 »
0
Espero me puedan ayudar con el siguiente programa, el cual despliega la cantidad de monedas que se deben dar como cambio, en la que se pide monto a pagar y dinero recibido.
Las monedas son de 25 centavos 10 centavos 5 centavos y 1 centavo

Tengo el programa el problema es cuando lo evalua para>
Monto a pagar: 4.63
Dinero recibido: 10
el resultado me roba 1 centavo, si cambio la condicion del ultimo ciclo a while(x>0)
el problema resulta al evaluar
Monto a pagar: 5
Dinero recibido: 10
roba 1 centavo
Cualquier ayuda la agradesco, no encuentro porque el problema.
Código: C
  1. /*Programa que calcula el cambio desplegando las monedas de 25, 10, 5 y 1 centavo
  2. */
  3.  
  4. #include <stdio.h>
  5. #include <conio.h>
  6.  
  7. #define ENTER 13 /*13 es la tecla Enter*/
  8.  
  9. void main(void);
  10. void pausa(void);
  11. void captura(void);
  12. void monedas(float);
  13.  
  14. void main(){
  15.    clrscr();
  16.    captura();
  17.    pausa();
  18. }
  19.  
  20. void pausa(){
  21.    printf("\nPresione Enter para continuar\n");
  22.    while(getch()!=ENTER);
  23. }
  24.  
  25. void captura(){
  26.    float monto,pago,cambio=0;
  27.    printf("Programa que calcula el cambio con monedas");
  28.    printf("\nInserte el total a pagar >");
  29.    scanf("%f",&monto);
  30.    printf("Inserte el dinero recibido >");
  31.    scanf("%f",&pago);
  32.    cambio=pago-monto;
  33.    printf("Su cambio es %.2f",cambio);
  34.    monedas(cambio);
  35. }
  36.  
  37. void monedas(float x){
  38.    int c25=0,c10=0,c5=0,c1=0;
  39.    while(x>0.25){
  40.       x-=0.25;
  41.       c25++;
  42.    }
  43.    printf("\n\nRegresar %d monedas de 25 centavos",c25);
  44.    while(x>0.1){
  45.       x-=0.1;
  46.       c10++;
  47.    }
  48.    printf("\nRegresar %d monedas de 10 centavos",c10);
  49.    while(x>0.05){
  50.       x-=0.05;
  51.       c5++;
  52.    }
  53.    printf("\nRegresar %d monedas de 10 centavos",c5);
  54.    while(x>=0.01){
  55.       c1++;
  56.       x-=0.01;
  57.       printf("\n%f",x);
  58.    }
  59.    printf("\nRegresar %d monedas de 10 centavos",c1);
  60. }
« última modificación: Lunes 19 de Septiembre de 2011, 06:02 por portirijillo »

ProfesorX

  • Moderador
  • ******
  • Mensajes: 796
  • Nacionalidad: mx
    • Ver Perfil
Re:No encuentro mi error
« Respuesta #1 en: Domingo 18 de Septiembre de 2011, 20:49 »
0
Hola portirijillo.

El problema que tienes ocurre debido al redondeo de los valores de tipo float.

Desafortunadamente, las computadoras solo entienden digitos binarios enteros (0 y 1), para representar los numeros de tipo flotante se escoge una codificacion para reprensentar un numero por medio de un exponente y una mantisa, pero al hacer esta conversion, en muchos casos el numero equivalente obtenido no es exactamente el numero que queremos almacenar, siempre habra un error de redondeo.

Puedes comprobarlo tu mismo, imprimiendo el valor guardado y veras que a veces no coincide el valor capturado/calculado con el valor verdadero:

Código: [Seleccionar]
void captura(){
    float monto,pago,cambio=0;
    printf("Programa que calcula el cambio con monedas");
    printf("\nInserte el total a pagar >");
    scanf("%f",&monto);
    // Lo probe y en mi caso capture 4.63, pero guardo
    // 4.6300001144, como podras notar tu mismo con .10f
    printf("%.10f\n", monto);
    printf("Inserte el dinero recibido >");
    scanf("%f",&pago);
    printf("%.10f\n", pago);
    cambio=pago-monto;
    // al poner .10f notaras que el valor de cambio en
    // realidad es 5.3699998856 y no 5.37 como pensabas
    printf("Su cambio es %.10f",cambio);
    monedas(cambio);
}

Por desgracia, no hay forma de evitar ni de predecir este error en el redondeo utilizando valores de tipo flotante.

La solucion que se me ocurre que podrias emplear es separar los centavos de las pesos (o dolares, quetzales, euros o cualquiera que sea la moneda que utilices, ya que no dices de que pais eres, en mexico nuestra moneda es el peso, asi que por eso digo pesos ;)), y tratar los centavos como si fueran cantidades enteras y no flotantes, es decir, en lugar de decir 0.10 pesos, dirias y capturarias 10 centavos. Luego para las cantidades en pesos multiplicalas por 100, de esa forma trabajaras solo con centavos, o sea en el caso de 5 pesos serian 500 centavos, luego sumale los centavos, y utiliza variables y operaciones enteras, al trabajar con enteros no hay problemas de redondeo, y obtendrias la cantidad en monedas exacta.

Tomando tu ejemplo, dirias algo como "deme la cantidad en pesos" y capturas 4, luego "dame la cantidad en centavos" y capturarias 63, luego multiplicas 4*100, da 400 y le sumas los centavos, da 463, y entonces haces las operaciones utilizando 463 en lugar de 4.63, obviamente restarias 25, 10, 5 y 1 en lugar de 0.25, 0.10, 0.5 y 0.1, no se si me di a entender.

Saludos y suerte :)

NOTA:
==================================================================
Este foro es para ayudar, aprender, compartir... usenlo para eso,
NO SE RESUELVEN DUDAS POR MENSAJE PRIVADO Y MENOS POR CORREO
==================================================================

portirijillo

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re:No encuentro mi error
« Respuesta #2 en: Lunes 19 de Septiembre de 2011, 06:02 »
0
Muchas gracias por tu respuesta, no se me habia ocurrido hacer lo que sugieres, y suena una solucion muy confiable, ya que no estaremos trabajando decimales. Me puse a pensar en cambios grandes y pequeños, y funciona perfecta tu solucion, aunque tambien se me ocurrio esta otra solucion. La dejo para cualquier otro usuario 2 soluciones dif.

Código: C
  1. /
  2.  
  3. #include <stdio.h>
  4. #include <conio.h>
  5.  
  6. #define ENTER 13 /*13 es la tecla Enter*/
  7.  
  8. void main(void);
  9. void pausa(void);
  10. void captura(void);
  11. void monedas(float);
  12.  
  13. void main(){
  14.    clrscr();
  15.    captura();
  16.    pausa();
  17. }
  18.  
  19. void pausa(){
  20.    printf("\nPresione Enter para continuar\n");
  21.    while(getch()!=ENTER);
  22. }
  23.  
  24. void captura(){
  25.    float monto,pago,cambio=0;
  26.    printf("Programa que calcula el cambio con monedas");
  27.    printf("\nInserte el total a pagar >");
  28.    scanf("%f",&monto);
  29.    printf("Inserte el dinero recibido >");
  30.    scanf("%f",&pago);
  31.    if(pago<monto)
  32.       printf("\nTe tomaron el pelo pide mas dinero");
  33.    else{
  34.       cambio=pago-monto;
  35.       printf("Su cambio es %.2f",cambio);
  36.       monedas(cambio);
  37.    }
  38. }
  39.  
  40. void monedas(float x){
  41.    printf("\n\nRegresar %.0f monedas de 25 centavos",x/0.25);
  42.    while(x>=0.25){ /*vamos ir decrementando el cambio hasta llegarlo a 0*/
  43.       x-=0.25;
  44.    }
  45.    printf("\nRegresar %.0f monedas de 10 centavos",x/0.1);
  46.    while(x>=0.1){
  47.       x-=0.1;
  48.    }
  49.    printf("\nRegresar %.0f monedas de 5 centavos",x/0.05);
  50.    while(x>=0.05){
  51.       x-=0.05;
  52.    }
  53.    printf("\nRegresar %.0f monedas de 1 centavo",x/0.01);
  54.    /*Por cuestiones de numeros flotantes no usamos ciclo para 1 centavo unicamente dividimos y da el mismo resultado*/
  55. }
  56.  
« última modificación: Lunes 11 de Junio de 2012, 06:45 por portirijillo »