C - Fehler bei Berechnung

OP #4814618
Lesenswert?
• ▲
▼
Hallo,
ich bin ein Neuling beim Programmieren und hätte eine Frage an euch.
Bei meinem Programm:
1
int Geld(){
2
   short Auswahl, Zwei=0, Eins=0, FZ=0, ZW=0, ZN=0, F=0, Z=0, E=0;
3
    double Wasser=1.38, Cola=1.76, Fanta=2.89, GeldE=0, Rueck=0
4

5
    printf("Welches Getraenk wuenschen Sie?\n\nDruecken Sie die:\n1    Wasser 1,38 Euro\n2    Cola 1,76 Euro\n3    Fanta 2,89 Euro\n\n");
6
    scanf("%hd",&Auswahl);
7

8
    while(Auswahl<1 || Auswahl>3){
9
    printf("Diese Nummer unterstuetz kein Produkt. Geben sie erneut die Zahl fuer ihr gewuenschtes Produkt ein: \nDruecken Sie die:\n1    Wasser 1,38 Euro\n2    Cola 1,76 Euro\n3    Fanta 2,89 Euro\n\n");
10
    scanf("%hd",&Auswahl);
11
    }
12

13
    printf("Geldeingabe >10Euro:");
14
    scanf("%lf",&GeldE);
15

16
    if(GeldE<10){
17
    printf("\nDer eingegebene Geldbetrag ist zu gering!");
18
    return -1;
19
    }
20

21
    if(Auswahl==1){
22
    Rueck=GeldE-Wasser;
23
    printf("\nIhr Wasser wird nun ausgegeben. Das Rueckgabegeld betraegt:  %.2lf Euro\n", Rueck);
24
    }
25

26
    if(Auswahl==2){
27
    Rueck=GeldE-Cola;
28
    printf("\nIhre Cola wird nun ausgegeben. Das Rueckgabegeld betraegt:  %.2lf Euro\n", Rueck);
29
    }
30

31
    if(Auswahl==3){
32
    Rueck=GeldE-Fanta;
33
    printf("\nIhre Fanta wird nun ausgegeben. Das Rueckgabegeld betraegt:  %.2lf Euro\n", Rueck);
34
    }
35

36
    while(Rueck>=2){
37
    Zwei+=1;
38
    Rueck-=2;
39
    }
40

41
    while(Rueck>=1){
42
    Eins+=1;
43
    Rueck-=1;
44
    }
45

46
    while(Rueck>=0.5){
47
    FZ+=1;
48
    Rueck-=0.5;
49
    }
50

51
    while(Rueck>=0.2){
52
    ZW+=1;
53
    Rueck-=0.2;
54
    }
55

56
    while(Rueck>=0.1){
57
    ZN+=1;
58
    Rueck-=0.1;
59
    }
60

61
    while(Rueck>=0.05){
62
    F+=1;
63
    Rueck-=0.05;
64
    }
65

66
    while(Rueck>=0.02){
67
    Z+=1;
68
    Rueck-=0.02;
69
    }
70

71
    while(Rueck!=0.0){
72
    E+=1;
73
    Rueck-=0.01;
74
    }
75

76
    printf("Ausgabe Zwei Euro Muenzen:%i \n",Zwei);
77
    printf("Ausgabe Ein Euro Muenzen:%i \n",Eins);
78
    printf("Ausgabe Fuenfzig Cent Muenzen:%i \n",FZ);
79
    printf("Ausgabe Zwanzig Cent Muenzen:%i \n",ZW);
80
    printf("Ausgabe Zehn Cent Muenzen:%i \n",ZN);
81
    printf("Ausgabe Fuenf Cent Muenzen:%i \n",F);
82
    printf("Ausgabe Zwei Cent Muenzen:%i \n",Z);
83
    printf("Ausgabe Ein Cent Muenzen:%i \n",E);
84

85
    return 0;
86
    }

Bei manchen Kombinationen wie z.B. wähle ich zuerst "1" an für 'Wasser'. 
Und gebe den Geldbetrag "39" ein. Dann zählt das Programm für 'Z' nicht 
hoch. Obwohl "Rueck>=0.02" sein sollte...

Könntet ihr mir da helfen?
Gast #4814630
Lesenswert?
• ▲
▼
> Obwohl "Rueck>=0.02" sein sollte...

Sollte, aber nicht ist. Wenn Du exakt rechnen willst, dann musst Du 
entweder andauern auf 0.01 Geldeinheiten runden oder (einfacher) Dich 
mit Festkommaarithmetik anfeinden.

HTH
#4814664
Lesenswert?
• ▲
▼
Runden ist meist keine runde Sache!

Gerade bei Werten, die mit Geld zu tun haben, ist die Ganzzahlarithmetik 
das Beste, was Du Dir antun kannst.

Bei modernen Rechnern hat ein Integer 64 Bit. Das sollte sogar für 
Automaten, die Kleinstaaten verkaufen, reichen. Haben diese keinen 
"natürlichen" Groß-Integer, so stellen die üblichen Bibliotheken auch 
den Wert: longint oder (u)int64_t zur Verfügung.

Intern sieht das ganze recht einfach aus: Ein Euro sind 100 Cent. Da 
gibt es nichts zu Runden und zu verstecken.

Bei der Ausgabe brauchst Du nur die einfache Division durch 100, setzt 
Dein Komma, und gibst die restlichen Cent aus.

Übrigens: Die gesetzlichen Vorschriften zum "wahren" Runden füllen 
viele, viele Seiten Gesetzestext.
#4815475
Lesenswert?
• ▲
▼
Wenn du wissen willst, weshalb das so ist, dann versuch mal, 0,1 als 
Summe von Binärbrüchen darzustellen. Also
    0,1 = (a * 1/2) + (b * 1/4) + (c * 1/8) + ...
mit a,b,c,... entweder 0 oder 1. Du wirst merken, dass das nie endet, 
dass also 0,1 in endlicher Stellenzahl so überhaupt nicht exakt 
darstellbar ist.
#4815485
Lesenswert?
• ▲
▼
A. K. schrieb:
> Wenn du wissen willst, weshalb das so ist, dann versuch mal, 0,1 als
> Summe von Binärbrüchen darzustellen. Also
>     0,1 = (a * 1/2) + (b * 1/4) + (c * 1/8) + ...
> mit a,b,c,... entweder 0 oder 1. Du wirst merken, dass das nie endet,
> dass also 0,1 in endlicher Stellenzahl so überhaupt nicht exakt
> darstellbar ist.

Oder anders gesagt: So wie im Dezimalsystem 1/3 eine periodische Zahl 
ist, ist im Dualsystem auch 1/5 (und damit auch 1/10) eine solche. Somit 
kann in einer entsprechenden Gleitkommazahl unabhängig von ihrer 
Genauigkeit der Wert 0,1 nicht gespeichert werden - es entsteht eine 
kleine Abweichung.
#4830575
Lesenswert?
• ▲
▼
Daniel S. schrieb:
> printf("Geldeingabe >10Euro:");
> scanf("%lf",&GeldE);
>
> if(GeldE<10){
> printf("\nDer eingegebene Geldbetrag ist zu gering!");
> return -1;
> }

"fachliche" Kritik (Leute, es ist Freitag!)

exakt 10 EUR ist also nicht eingebbar (<10 wird nicht akzeptiert, und 
Betrag muß >10 sein). Also müßte ich 20 EUR eingeben. Und bekomme dann 
20,00 -1,38 = 18,62 EUR Wechselgeld raus, womöglich in Münzen.

Vermutlich ist der Automat ne Klimperkiste, mit dem Bauch voller 
Wechselgeld. Und die Kunden müssen immer große Scheine mithaben, um 
überhaupt ein Getränk ziehen zu können.

Und 1,38 als Betrag? Marketingtechnisch eh ein Preis, der eher 
ungeschickt ist (noch schlechtere Akzeptanz hätte vielleich 1,34 oder 
1,37 ans krummer Wert).

Ausserdem: 1,38 für ein Wasser, vermutlich sogar nur 0,33 Liter. Macht 
4,14 EUR pro Liter! Dafür bekommt man ja schon ne Flasche Wein. Naja, 
vielleicht sinds Flughafen-Preise.

Schönes Wochenende!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.