C++ kleine Frage zu meinem If-code

Alexon

Ensign
Registriert
Sep. 2008
Beiträge
222
Hi,
in folgendem Code lese ich einen Float-Wert in meine Funktion und überprüfe ihn auf gültige Werte.
Allerdings tritt hier ein Bug auf. Ist der Wert 0.2, 0.1 oder 0.05 so wird das Else: ... ausgeführt, ab 0.50 funktioniert es.
Code:
int pruefeGeldstueck(float pruefe)               
{
//pruefe ist zB .30 oder 2
    if ((pruefe == .05) || (pruefe == .10) || (pruefe == .20) || (pruefe == .50) || (pruefe == 1.00) || (pruefe == 2.00)) 
    //if ((pruefe != .05) && (...) ...) does not work!? for 20 cent
    return 1; //<-then
    printf ("--- ungueltiges Geldstueck ---"); 
    return 0;    
}

Woran liegt das?
Falls jemand es besser sieht, wenn er es ausprobiert, hier mein komplettes Programm.
Code:
//Getränkeautomat
#include <stdio.h>
#include <stdlib.h>

//----Prototypen---                                //ohne geschweifte Klammern!
void benutzerInformation();
int auswahlSorte();
float ermittlePreis();
int eingabeMenge();
void bezahlen(float gesamtPreis);                  
int pruefeGeldstueck(float);                        
void ausgabe();
void geldrueckgabe(float);                         //A4 float!

//----Globale Variablen---
float zuvielgezahlt=0.0;                           //Aufgabe3

//----main----------------------
int main()
{                
  //-----Variablen
  int sorte, menge;
  const int anfang=1; 
  float preis, gesamtPreis;
  //-----Ausführung
  benutzerInformation(anfang);
  sorte = auswahlSorte();
  preis = ermittlePreis(sorte);
  menge = eingabeMenge();
  
  gesamtPreis = preis * menge;
  
  bezahlen (gesamtPreis);
  ausgabe (sorte, menge);
  
  benutzerInformation(!anfang);
  
  system("PAUSE");
} //--Ende main-----------------
//----Nebenfunktionen---------
//
void benutzerInformation (int istAnfang)
{
     if (istAnfang)
     printf ("Info II Getraenke-Automat V.1\n\n");
     else
     { printf("\nVielen Dank! \n"
     "Bitte entnehmen sie ihre Getraenke.\n");
     } return;
}          
//
int auswahlSorte()
{
    int sorte;
    printf("\nWaehlen sie ihr Getraenk aus:\n");
    printf ("1) Wasser (0,50 Euro)\n");
    printf ("2) Cola   (1,00 Euro)\n");
    printf ("3) Bier   (2,00 Euro)\n\n");
    printf ("Geben sie 1, 2 oder 3 ein: ");
    scanf ("%d", &sorte);
    return sorte;
}
//
int eingabeMenge()
{
    int menge=1;
    printf ("\nGeben sie die gewuenschte Menge ein: ");
    scanf("%d",&menge);
    return menge;
}
//
float ermittlePreis(int sorte)
{
      float preis; 
      switch (sorte)
      {
             case 1 :preis =0.5;break;
             case 2 :preis =1.0;break;
             case 3 :preis =2.0;break;
             default:preis =0;
      }
      return preis;
}
// -----------Aufgabe 2-------------     
void bezahlen(float betrag) 
{
     printf ("\n--- Bezahlvorgang ---\n");
     float einwurf;
     float rueckgabe=0.0;                                        //A2
     do
     {     printf("Es fehlen noch %.2fEuro.", betrag);
           printf("\nBitte werfen sie ein Geldstueck ein: ");
           scanf ("%f",&einwurf);
           //                                                    //A2
           
           if (einwurf==0.0)
           { printf("\n Rueckgabe von %.2fEuro",rueckgabe);
             geldrueckgabe(rueckgabe);
             return;
           }
           //                                                    
           if (pruefeGeldstueck (einwurf) )
           { betrag -= einwurf;                                  //eingeworfenen Betrag anrechnen    
           rueckgabe +=einwurf;
           }
     } while (betrag > 0.0);
     zuvielgezahlt = -betrag;                                    //A3 globale Variable
     return;
}
// 
int pruefeGeldstueck(float pruefe)               
{
    if ((pruefe == .05) || (pruefe == .10) || (pruefe == .20) || (pruefe == .50) || (pruefe == 1.00) || (pruefe == 2.00)) 
    //if ((pruefe != .05) && (...) ...) does not work!? for 20 cent
    return 1; //<-then
    printf ("--- ungueltiges Geldstueck ---"); 
    return 0;    
} 
//
void ausgabe(int sorte, int menge)
{
     printf("\n--- Getraenkeausgabe ---\n");
     int i;
     for (i=0; i<menge; i++)
     { printf("\nFlasche (#%d von %d) der Sorte %d" 
                         " wurde ausgegeben.", i+1, menge, sorte);
     }
     if (zuvielgezahlt >= 0)                                     //A3
     {printf ("\nSie bekommen %.2fEuro zurueck",zuvielgezahlt);  //A3
     geldrueckgabe(zuvielgezahlt);
     }
     
     return;
}

// ----------Aufgabe 4-------------
void geldrueckgabe(float rest)                                   //A4
{
     //höchstens 1.50 zuviel gezahlt.
     printf("\n");
     //Prüfen des größten Geldstücks:
     // 1Euro
     if (rest >= 1)       //Am schnellsten mit einer allgemeinen Abfrage, dann detailliert
     {              if ((rest - 1) == 0)                                    
                    {              printf ("1.00Euro\n");
                                   return;
                    }
                    printf ("1.00Euro\n");
                    rest -=1;
     }
     //.50Euro
     if (rest >= .5)
     {              if ((rest - .50) == 0)                    //ausschließen des größtmöglichen Geldstücks
                    {              printf (".50Euro\n");
                                   return;
                    }
                    printf ("0.50Euro\n");
                    rest -=.50;
     }
     //.20Euro, da gibt es eine Ausname!
     while (rest>=.20)
     {     if ((rest - .2) == 0)                              //ausschließen des größtenmöglichen Geldstücks
           {        printf ("0.20Euro\n");
                    return;
           }
           printf ("0.20Euro\n");
           rest -=.20;
     } //End (while) .20Euro
     //.10Euro
     if (rest >= .10)
     {              if ((rest - .10) == 0)                     //ausschließen des größtmöglichen Geldstücks
                    {              printf ("0.10Euro\n");
                                   return;
                    }
                    printf ("0.10Euro\n");
                    rest -=.10;
     }
     //.05Euro
     if (rest >= .05)
     {              if ((rest - .05) == 0)                     //ausschließen des größtmöglichen Geldstücks
                    {              printf ("0.05Euro\n");
                                   return;
                    }
                    printf ("0.05Euro\n");
                    rest -=.05;
     }
}    //Ende Void geldrueckgabe
 
Zuletzt bearbeitet:
Ich habe nicht genau hingeschaut, ob es hier das Problem ist, aber
generell: Pruefe Fliesskommazahlen nie auf exakte Gleichheit

Denn evlt ist die Konstante 0.1 nicht als endlicher Dezimalbruch im 2er System darstellbar,
und das Ergebnis einer Rechnung damit ist nie exakt gleich einer Konstante mit der Du vergleichst.

Stelle alles auf Cent und Integer um, ist sicherer, oder teste mit einem kleinen Epsilon

wert < soll+eps && wert > soll-eps
 
Liegt evtl daran, dass sich die Zahlen nicht exakt als Gleitkommazahl darstellen lassen...

Um das zu begründen müsste man etwas weiter ausholen, da würde ich den Wiki-Artikel zum Thema Gleitkommazahlen/Fließkommazahlen empfehlen..

0.5 gehört zu den Zahlen, die sich exakt ausdrücken lassen... vereinfacht gesagt lassen sich genau ausdrücken (nur im Nachkommabereich jetzt):
* 0,5 und immer wieder die Hälfte der Zahl (also 0.5, 0.25, 0.125, 0.0625, ....)
* alle Summen aus den genauen Zahlen (also z.B. 0.75, 0.875, 0.3125, ...)

Lösung:
Nicht auf Gleichheit prüfen sondern auf "etwa gleich"
dafür die Differenz zum abgefragten Wert berechnen und schauen, ob der in etwa 0 is

in etwa so:
abs(pruefe - 0.1) < 0.001

(abs sorgt dafür, dass es egal is, ob die Zahl leicht größer oder leicht kleiner als 0,1 ist hier)
 
@leboh Hmm stimmt an die binär-Speicherung im Computer habe ich nicht garnicht gedacht.

Werde speziell diese Funktion mit Cent versuchen. Für die Aufgabenstellung soll ich allerdings floats und Euro benutzen...

das mit dem "kleinen Epsilon" verstehe ich nicht ganz: Wie klein darf das Epsilon noch sein, damit sich 0.20 Euro von 0.19 bzw 0.21 Euro unterscheiden lässt?

danke

Edit:
Ok kapiert, funktioniert nun alles. danke
 
Zuletzt bearbeitet:
so solltest für dein programm kein float verwenden. es macht hier ohnehin keinen sinn.
die kleinste einheit beim euro ist der cent. deshalb rechne einfach integer mit cents. da sind rundungsfehler nämlich ausgeschlossen.
 
Wenn es die Aufgabenstellung war das mit Float zu machen, war es evtl der Hintergrund der Aufgabe, auf den Du gestossen bist :-)
 
hat das Programm Getränkeautomat funktioniert?
Würde mich freuen, wenn du es mir zu schicken könntest.
 
Zurück
Oben