Problem mit einem Programm
-
Hallo Community,
ich habe ein Problem mit einem Programm das ich geschrieben habe. Und zwar generiert das Programm einen zufälligen Betrag bis 100€. Danach soll der Benutzer so oft eine Einzahlung machen, bis der gewünschte Betrag erreicht ist. Wenn zu viel Geld eingezahlt wurde, soll das Programm das Restgeld vom größten zum kleinsten Schein oder Münze ausgeben (also nur auf dem Bildschirm ausgeben).
Das Programm ist in 3 Funktionen unterteilt.Die 1. Funktion erstellt die Zufallszahl.
Die 2. Funktion fragt den Benutzer nach seiner Einzahlung
Die 3. Funktion teilt das Rückgeld in Geldscheine und Münzen auf.Das alles klappt soweit auch. Jedoch gibt es ab und zu ein Problem bei der Ausgabe des Geldes (also in Funktion Nummer 3). Ein kleines Beispiel:
Alle Benutzereingaben werden FETT hinterlegt.
Ihr Weihnachtsgeschnk kostest 92.12 Euro. Sie haben noch 92.12 Euro zu Zahlen. Ihre Zahlung: [b]96.32[/b] Sie bekommen 4.20 Euro in: 2.00 Euro 2.00 Euro 0.10 Cent 0.05 Cent 0.02 Cent 0.02 Cent zurueck.
Komischerweise tritt dieser Fehler bei willkürlichen Beträgen auf. Hier kann man sehen das 1 Cent zu wenig ausgegeben wird. Bei einer anderen Zahl wie im unteren Beispiel wird der selbe Betrag zurück gezahlt. Hier jedoch richtig. Das einzige was sich geändert hat ist die Zufallszahl,
Ihr Weihnachtsgeschenk kostest 76.25 Euro. Sie haben noch 76.25 Euro zu Zahlen. Ihre Zahlung: [b]80.45[/b] Sie bekommen 4.20 Euro in: 2.00 Euro 2.00 Euro 0.20 Cent zurueck.
Ich habe einen Kollegen der das selbe Programm geschrieben hat, jedoch mit Integer als Datentyp, dabei hat er nur mit Cent-Werten gearbeitet. Dies ist aber in der Ausgabe nicht so schön.
Meine Vermutung ist das es irgendetwas mit double zu tun hat. Kann mich aber auch irren.
Hier habe ich das Programm mal gepostet. Wie gesagt der Fehler muss irgendwo in der Funktion "rueckzahlung" liegen.
#include <stdio.h> #include <stdlib.h> #include <time.h> double kaufpreis (void); double zahlung(double btr1, double kp1); double rueckzahlung(double rueckgeld); // Hauptfunktion int main() { double kp, btr; kp = kaufpreis(); printf("Ihr Weinachtsgeschenk kostest %.2lf Euro. \n\n", kp); printf("Sie haben noch %.2lf Euro zu zahlen. Ihre Zahlung: "); scanf("%lf", &btr); while(getchar() != '\n'); btr = zahlung(btr,kp); rueckzahlung(btr); return 0; } /* Funktion zur Generation eines Zufallsbetrags bis 100 */ double kaufpreis (void) { double betrag; srand( time(NULL) ); rand(); betrag= rand() % 10000; betrag /= 100; return betrag; } /* Funktion zur Eingabe der Zahlung. Berechnung der Differenz zwischen Kaufpreis und Zahlung. Dies wird solange wiederholt bis die Zahlung größer als der Kaufpreis ist. */ double zahlung(double btr1, double kp1){ double rueckgeld; while (btr1 <= kp1){ kp1 = kp1-btr1; printf("Sie haben noch %.2lf zahlen. Ihre Zahlung: " , kp1); scanf("%lf", &btr1); while(getchar() != '\n'); } printf("\n"); rueckgeld = btr1 - kp1; return rueckgeld; } /* Funktion zur Ausgabe des Rueckgeldes in Euro und Cent */ double rueckzahlung(double rueckgeld){ int i; double geld[15] = {500, 200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01}; printf("Sie bekommen %.2lf Euro in: ", rueckgeld); for(i=0 ; i<=14 ; i++){ while(rueckgeld >= geld[i]){ if(geld[i] >= 1){ printf("%.2lf Euro ", geld[i]); rueckgeld -= geld[i]; } else{ printf("%.2lf Cent ", geld[i]); rueckgeld -= geld[i]; } } } printf("zurueck.\n"); return 0; }
Da dies mein 1. Thread ist könnt ihr mich gerne auf meine Fehler, die ich in meinem Beitrag gemacht habe, hinweisen. Ich wäre dankbar wenn mir jemand helfen könnte.
Gruß akristmann
-
Lies Dir mal diesen Thread durch:
http://www.c-plusplus.net/forum/279548
-
Bei Fließkommazahlen kommt es immer zu Rundungsfehlern da diese intern nicht vollständig dargestellt werden können.
Deshlab rechnet man bei Geldbeträgen besser mit Cent und Integer.
Die Ausgabe kannst du so machen:
if(geld[i] >= 100) { printf("%d,%02d Euro ", geld[i]/100, geld[i]%100); } else { printf("%d Cent ", geld[i]); } rueckgeld -= geld[i];
-
Das nenne ich doch mal eine qualifizierte Frage in ansprechender Form.
Sogar den Eingabepuffer löscht du standardkonform, da muss ich meine jüngste Aussage diesbezüglich wohl von 99% auf 98% korrigieren.In Zusammenhang mit Fließkommavergleichoperationen würde ich immer mit Fließkommakonstanten arbeiten, ebenso auf Gleichheitsprüfungen verzichten, auch ist %lf bei printf nicht Standard, also etwa:
/* Funktion zur Ausgabe des Rueckgeldes in Euro und Cent */ double gerundetZweistellig(double d) { d *= 100.0f; d = d > floor(d)+0.5f ? ceil(d) : floor(d); d /= 100.0f; return d; } double rueckzahlung(double rueckgeld){ int i; double geld[] = {500, 200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01}; printf("Sie bekommen %.2f Euro in: ", rueckgeld); for(i=0 ; i<sizeof geld/sizeof*geld ; i++){ while(gerundetZweistellig(rueckgeld) > gerundetZweistellig(geld[i])){ if(gerundetZweistellig(geld[i]) < 1.0f){ printf("%.2f Cent", geld[i]); } else{ printf("%.2f Euro", geld[i]); } rueckgeld -= geld[i]; } } printf("zurueck.\n"); return 0; }
Was ist denn so schlimm an Integer-Cent Berechnungen, die Ausgaben kannst du genauso wie bei double gestalten.
-
Super! Vielen Dank für die Antworten.
ja stimmt Double hat ja nur eine Genauigkeit bis zur 15. Stelle glaube ich. Ich werde das dann auch mit dem Integer machen wie Dirkb das gesagt hat machen. Bzw. werde ich das erst mal mit den Fließkommakonstanten probieren wie Wutz das gesagt hat.
@Wutz: Was war denn deine jüngste Aussage?
Gruß akristmann
-
akristmann schrieb:
ja stimmt Double hat ja nur eine Genauigkeit bis zur 15. Stelle glaube ich. Ich werde das dann auch mit dem Integer machen wie Dirkb das gesagt hat machen. Bzw. werde ich das erst mal mit den Fließkommakonstanten probieren wie Wutz das gesagt hat.
@Wutz: Was war denn deine jüngste Aussage?
Für Deine Belange ist es erstmal irrelevant, ob Du das mit double oder aufgeteilten Ints machst, solange Du nicht Milliardenbeträge fortlaufend verzinst oder so etwas. Sagen wir mal so, daß ein double finanztechnischen Ansprüchen nicht genügt, aber die Vorschriften, wann und wie gerundet wird, so verzwickt sind, daß es mit Ints für Euro und Cent auch nicht getan wäre.
Achja, wutz hat sich gefreut, daß Du den Buffer korrekt leerst und nicht wie die meisten (wenn überhaupt) mit fflush(stdin), das liefert nämlich undef. Verhalten.90% der "wenn ich das drücke, passiert Unsinn"- Anfragen gehen auf diese Basisfehler zurück.
-
Gib doch mal in deiner ruckzahlung() einfach vor dem return das rueckgeld aus.
Evtl. sogar mit "%.17f", dann siehst du ja was noch übrig ist.