Float Variablen in if Abfragen.



  • Hallo zusammen,

    Ich bräuchte einen Tipp zum Thema floats in if else von euch.
    Meine Frage bezieht sich diesmal auf das Verwenden von float Variablen in if Abfragen.
    Kann es sein, dass manche Eingaben wie z.b. 0.10 nicht erkannt werden können?

    Der Hintergrund:
    Ich habe ein kleines Programm geschrieben, dass nach einem bestimmten Euro Betrag verlangt.
    Erlaubte Eingaben sind aber nur Münzen die es tatsächlich gibt(0.10, 0.20...)
    Eingaben wie z.B. 0.33 sind nicht erlaubt.

    Hier die Funktion, die die Eingabe kontrolliert:
    [code'c']
    int geldstueck (float geld)
    {
    if (geld == 0.01 || geld == 0.02 || geld == 0.05 || geld == 0.10 || geld == 0.20 || geld == 0.50 || geld == 1.00 || geld == 2.00)
    {
    return 1;
    } else {
    return 0;
    }}
    [/code]

    Mein Problem ist jetzt, dass alle Eingaben außer 0.50, 1.00 und 2.00 als falsch angesehen werden, obowhl sie ja mit in den Klammern stehen.

    Aufgerufen wird die Funktion übrigens über eine switch case Abfrage:

    switch (geldstueck(geld))
    {
    case 1:
    einwurf = einwurf + geld;
    break;
    case 0:
    printf("Die Münze, die Sie eingeworfen haben, ist ungültig.\n");
    geld = 0;
    break;
    }
    

    Ich dachte zuerst, dass es daran liegen könnte, dass switch case ja keine floats einlesen kann.
    Aber die Variable wird ja in dem Fall nur an die Funktion weitergegeben.
    Habt ihr einen Tipp für mich, woran das liegen könnte?

    Viele Grüße


  • Mod

    0.1 ist im Binärsystem (mit dem der Computer intern arbeitet) ein periodischer Bruch. Also so etwas wie 1/3 im Dezimalsystem. Mit dem float hast du 23 binäre Stellen davon gespeichert. (Dezimale Analogie: Du hast 0.333333 gespeichert). Nun vergleichst du es mit dem 56'stelligen double Wert 0.1 (solche Konstanten im Programm haben den Typ double. 0.1f wäre vom Typ float). Dezimale Analogie: Du vergleichst 0.333333 mit 0.333333333333333. Daher sind die Werte nicht gleich.

    Die Lösung wäre jedoch nicht, alles mit double oder alles mit float zu berechnen. Nein, die Wahl von Fließkommazahlen für Geld an sich ist falsch. Du lässt dich hier von einer Ähnlichkeit in der Darstellung (Zahlen mit Komma drin) zu einem Fehlschluss über das semantische Verhalten verleiten. Ein ähnlicher Fehlschluss wäre die Speicherung einer Telefon- oder Kontonummer oder Postleitzahl als Ganzzahl (denk mal an die Postleitzahl von Dresden).

    Die Fließkommazahl ist die Computerannäherung an kontinuierliche Größen, das heißt an Größen, die beliebig fein unterteilbar sind. Geld hingegen kommt immer in ganzen Einheiten, es ist eine diskrete Größe. Entsprechend muss auch der Datentyp so gewählt sein, dass er dies ausdrückt. Die wahrscheinlich beste Lösung wäre wohl ein komplexer Datentyp basierend auf Fixkommazahlen. Da mir bewusst ist, dass du da als Anfänger hoffnungslos überfordert wärst, empfehle ich als Krücke, eine Ganzzahl (also int oder ähnliches) zu benutzen. Du rechnest dann eben einfach in Cent. Oder Zehntelcent, wenn du es genauer brauchst. Das ist recht einfach und du kommst damit sehr weit (Im Prinzip kannst du damit praktisch alles machen, so lange du dein Programm nicht im internationalen Finanzhandel einsetzt).

    Der Benutzer kann natürlich trotzdem seine Angaben in Euro mit Komma machen. Du musst es bloß ein bisschen clever lesen. Zum Beispiel:

    int get_cent() // Könnte noch Fehlerprüfung vertragen
                   // und die Möglichkeit, nur ganze Euros einzugeben.
                   // Soll bloß ein fixes Beispiel sein.
    {
        int euro, cent;
        scanf("%d.%d", &euro, &cent);
        return euro*100 + cent;
    }
    


  • Hallo Seppj,

    dank dir für die Erklärung.
    Da wär ich echt nicht drauf gekommen. Mit double hatte ich es sogar schon versucht.
    Allerdings funktionierte danach gar nichts mehr. Sprich: Alle Zahlen, die ich eingegeben hatte, wurden nicht mehr akzeptiert.
    Den Begriff Fixkomma, habe ich sogar schon irgendwo gelesen. Da werde ich mich nochmal kundig machen.

    Eines steht fest:
    Das Buch, das ich momentan verwende, sollte ausgetauscht werden.
    Da wird nämlich seit Beginn gnadenlos all das gemacht, was du hier als falsch bezeichnest.
    Geld ind Float, Telefonnummern in int...
    Aber mal ganz aus Neugier.
    Wie speichert man denn optimal Telefonnummern, wenn man dies nicht mit einer int Variable tun sollte?

    Als Behelfslösung habe ich es jetzt so gelöst.

    int geldstueck (float geld)
    {
    int i=(int)(geld*100);
    if (i == 1 || i == 2 || i == 5 || i == 10 || i == 20 || i == 50 || i == 100 || i == 200)
    {
    return 1;
    } else {
    return 0;
    }}
    

    Das funktioniert jetzt einwandfrei.
    Also danke nochmal!



  • BIOSzillator schrieb:

    Wie speichert man denn optimal Telefonnummern, wenn man dies nicht mit einer int Variable tun sollte?

    Also ich kenne Telefonnumern in Formaten wie zum Beispiel
    +49 6657 4456789 //typisch für im handy, weil man cool ist
    01573-6655493 //recht normal
    01573/6655493 //traditionell
    4567 Q //im Ortsnetz mit Abrufbeantworter traditionell
    4567 (AB) //im Ortsnetz mit Abrufbeantworter modern

    Das kann man alles mit struct{int Land/int Vorwahl/int Nachwahl/bool AB} abdecken, aber sowas geht meiner Erfahrung immer nach hinten los. Sie Sekretärennen fühne sich angepisst, eine Nummer in drei Feldern plus Checkbox eintippen zu müssen. Sie selber benutzen die Nummern doch dann wieder. In ihrem Job sind sie viel schauer als wir.

    Würde string nehmen und darauf bestehen, daß die Sekretärinnen keinen Scheiß eingeben.

    Mancher hat sogar mehrere Nummern, die man auf Gedeih und Verreck nicht sinnvoll in die Datenbank geklopft kriegt. Hans hat zum Beispiel:
    22767 (Erziehungsberechtigte, tagsüber nicht da)
    4459 (Notfallnummer, die Oma)

    Ein Problem, sorry.

    Ich mache für soweas gerne die Telefonnummer.hpp mit drin

    //typedef std::string Telefonnummer
    Uups, wir sind ja in C. 
    struct Telefonnummer{
       char* data;
    };
    

    und kanns an zentraler Stelle ändern, wenn nötig. Ist aber nie nötig irgendwie.


  • Mod

    volkard schrieb:

    struct{int Land/int Vorwahl/int Nachwahl/bool AB}

    Warum als Zahlenwert? Willst du den Durchschnittswert aller Telefonnummern ausrechnen? Ich finde bestimmt auch irgendwo eine Nummer, die mehr Stellen in der Nachwahl hat als ein üblicher int könnte.



  • SeppJ schrieb:

    volkard schrieb:

    struct{int Land/int Vorwahl/int Nachwahl/bool AB}

    Warum als Zahlenwert? Willst du den Durchschnittswert aller Telefonnummern ausrechnen? Ich finde bestimmt auch irgendwo eine Nummer, die mehr Stellen in der Nachwahl hat als ein üblicher int könnte.

    Hast recht. int passt eigentlich gar nicht. man will mit telefonnummern ja nicht rechnen. und wenn man sie vergleichen will, sortieren, dann lexikografisch, wie strings. ich war gewolft, sorry.



  • So, dann will ich mich uach nochmal melden.
    Danke euch beiden für die Tipps.
    Ich werde es dann mal mit string probieren. In dem Buch, das ich benutze, sind sie allerdings noch nicht an der Reihe. Würde vielleicht auch erklären, warum wir bis jetzt immer Telefonnummern in int gespeichert haben.



  • Die Tel.Nr. als int kann doch völlig unterschiedlich interpretiert werden:
    Aus 0800 12234 wird bei Speicherung als int 80012234, aus 0049 2304 123 wird 492304123 ...
    Da du also nie weißt, wieviel führende Nullen Deine Tel.Nr. haben soll, ist int untauglich.



  • Belli schrieb:

    Aus 0800 12234 wird bei Speicherung als int 80012234, aus 0049 2304 123 wird 492304123 ...

    nein, er wird schimpfen, weil er oktal die 8 nicht will.



  • Hier mal ein Beispiel einer Telefonnummer, die von Kunden in D so direkt eingeben wird. Die Zahlen sind frei erfunden. Die Anzahl der Stellen nicht.

    0.... - Vorwahl: 5 Ziffern
    99999 - Rufnummer hier 5 Ziffern, können je nach Ortsnetz auch mehr sein
    01010 - Kunden-ID
    2 - Hauptgruppe
    3 - Untergruppe
    1 - Bonus?
    88 - Anzahl der Positionen des Auftrags, max. 99

    Also habt ihr bis hier schon 20 Ziffern ohne Dialog bis hier.

    Eventuell noch sind folgend Raute oder Stern gefragt.

    Diese Zahlenfolge kann im folgenden Dialog noch erweitert werden.

    Dann gab/gibt es ja auch die Netze wo die Telefonnummern nicht nur aus Zahlen, sondern aus Buchstabenfolgen zusammen gesetzt sind.

    Aber solche Sachen findet man in einer "normalen" Telefonliste selten.
    Eine oder zwei führende Nullen sind da eher relevant.



  • elise schrieb:

    Belli schrieb:

    Aus 0800 12234 wird bei Speicherung als int 80012234, aus 0049 2304 123 wird 492304123 ...

    nein, er wird schimpfen, weil er oktal die 8 nicht will.

    #include <stdio.h>
    
    int main()
    {
       int telnr;
    
       printf("Gib Tel.Nr ein:\n");
       scanf("%d", &telnr);
       printf("Eingabe war: %d", telnr);
    }
    

    Eingabe: 0800123
    Ausgabe: 800123



  • #include <stdio.h>
    
    int main()
    {
    	int telnr =  0800123;
    }
    

    error: invalid digit "8" in octal constant

    meinte ich, falls du sie speicherst als int 😉



  • Dein Code ist ziemlich statisch für 'ne Anwendung, die Telefonnummern verwalten soll ...


Anmelden zum Antworten