Rückgabe von Wechselgeld nach einem Kauf


  • Mod

    Clonex schrieb:

    Dann werde ich das mal versuchen. Laufen tut das Programm zur Zeit ohne das der Compiler meckert. Nur halt die Wechselgeldberechnung geht leider nicht. Geld grundsätzliche nicht in double stecken oder nur wegen der while schleifen? liegt es nur daran das es double Werte sind und mir das Programm deshalb nicht das richtige wechsel geld berechnet oder ist der Ansatz mittels der while schleifen schlecht?

    Danke vielmals

    Der double ist generell ein schlechter Datentyp für Geld. Geld kommt in kleinsten Einheiten, den Cents. doubles modellieren hingegen das Kontinuum (soweit dies auf einem Digitalrechner geht). Stell dir vor, du würdest die Aufgabe auf Papier grafisch lösen. Wenn du auf komplett weißem Papier malst, wirst du nie ein exaktes Ergebnis bekommten. Auf Kästchenpapier ist das hingegen ganz einfach.



  • Und um den Schleifenjungle etwas zu entwirren, böte sich irgendeine Datenstruktur an, in der du die möglichen Schein-/Münzengrößen drinhast, damit du da dann nurnoch durchrennen musst.



  • Meinst du ein Array?



  • Wenns sein muss auch ein Array. Sonst halt ein Vector oder irgendwas in der Art.



  • Wie eingangs schon erwähnt habe ich gerade erst angefangen mit der c++ Programmierung das einzige was ich kenne ist bisher ein array. Habe es auch anfangs mit einem versucht. Hat aber leider nicht geklappt. Weiß auch nicht was ich da falsch gemacht habe. Dann bin ich auf die Idee mit den while schleifen gekommen. Dachte das wäre so leichter. Aber auch das hat nicht so funktioniert wie ich es mir vorgestellt habe und jetzt wollte ich mir mal hier Rat holen da ich nicht mehr weiter wusste.



  • OK, ich schreib dir mal grad eins mit nem vector, 1 mom. 😉



  • Kannst du mir auf die Sprünge helfen wie ich das mit einem array umsetzen könnte?



  • Geht sicher auch wesentlich eleganter und wiederverwendbarer, aber damit du siehst, wie ich es meine, reichts, denk ich.

    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main()
    {
    	int kaufbetrag, gezahlt;
    	cout << "Bitte geben Sie den den Kaufbetrag in Cent ein: " << endl;
    	cin >> kaufbetrag;
    	cout << "Bitte geben Sie den Gezahlten Betrag in Cent ein: " << endl;
    	cin >> gezahlt;
    
    	int wechselgeld( gezahlt - kaufbetrag );
    	if ( wechselgeld < 0 )
    	{
    		cout << "zu wenig, cu" << endl;
    		return 1;
    	}
    	if ( wechselgeld == 0 )
    	{
    		cout << "passt, cu" << endl;
    		return 0;
    	}
    
    	vector <int> geldEinheiten;
    	geldEinheiten.reserve( 15 );
    	geldEinheiten.push_back( 50000 );
    	geldEinheiten.push_back( 20000 );
    	geldEinheiten.push_back( 10000 );
    	geldEinheiten.push_back(  5000 );
    	geldEinheiten.push_back(  2000 );
    	geldEinheiten.push_back(  1000 );
    	geldEinheiten.push_back(   500 );
    	geldEinheiten.push_back(   200 );
    	geldEinheiten.push_back(   100 );
    	geldEinheiten.push_back(    50 );
    	geldEinheiten.push_back(    20 );
    	geldEinheiten.push_back(    10 );
    	geldEinheiten.push_back(     5 );
    	geldEinheiten.push_back(     2 );
    	geldEinheiten.push_back(     1 );
    
    	cout << "Im Wechselgeld sind:" << endl;
    	for ( vector <int>::const_iterator it( geldEinheiten.begin() ); it != geldEinheiten.end(); ++it )
    	{
    		int anzahl( 0 );
    		while ( *it <= wechselgeld )
    		{
    			++anzahl;
    			wechselgeld -= *it;
    		}
    		cout << anzahl << " Gegenstaende, die einen Wert von " << *it << " Cent repräsentieren." << endl;
    	}
    	return 0;
    }
    


  • Hast du auch einen Tipp wie ich das mit einem Array mache? Ich bekomme es nicht hin... 😞
    😕



  • Klar kannst du dort oben den vector<> durch ein Array und die Iteratoren durch Index-Zugriffe ersetzen. Aber die STL-Containerklassen sind wesentlich flexibler als nackte Arrays, also solltest du sie auch nutzen 😉



  • Clonex schrieb:

    Hast du auch einen Tipp wie ich das mit einem Array mache? Ich bekomme es nicht hin... 😞
    😕

    Normalerweise fass ich ekelwutzige Arrays nur an wenn es sich gar nicht vermeiden lässt, weil der code dadurch (wie du gleich sehen wirst) automatisch und unvermeidlich komisch wird, aber weil du es bist. 😉

    #include <iostream>
    #include <math.h>
    using namespace std;
    
    #define AbGehtDiePost for ( int n( 14 ); n >= 0; --n )
    
    int main()
    {
    	int kaufbetrag, gezahlt;
    	cout << "Bitte geben Sie den den Kaufbetrag in Cent ein: " << endl;
    	cin >> kaufbetrag;
    	cout << "Bitte geben Sie den Gezahlten Betrag in Cent ein: " << endl;
    	cin >> gezahlt;
    
    	int wechselgeld( gezahlt - kaufbetrag );
    	if ( wechselgeld < 0 )
    	{
    		cout << "zu wenig, cu" << endl;
    		return 1;
    	}
    	if ( wechselgeld == 0 )
    	{
    		cout << "passt, cu" << endl;
    		return 0;
    	}
    
    	int geldEinheiten[15]; // boeses Array
    	AbGehtDiePost
    	{
    		geldEinheiten[n] = (pow((n%3),2) + 1)*pow(10,floor(n/3));
    	}
    
    	cout << "Im Wechselgeld sind:" << endl;
    	AbGehtDiePost
    	{
    		int anzahl( 0 );
    		while ( *(geldEinheiten+n) <= wechselgeld )
    		{
    			++anzahl;
    			wechselgeld -= *(geldEinheiten+n);
    		}
    		cout << anzahl << " Gegenstaende, die einen Wert von " << *(geldEinheiten+n) << " Cent repräsentieren." << endl;
    	}
    	return 0;
    }
    


  • Dobi schrieb:

    Clonex schrieb:

    Hast du auch einen Tipp wie ich das mit einem Array mache? Ich bekomme es nicht hin... 😞
    😕

    Normalerweise fass ich ekelwutzige Arrays nur an wenn es sich gar nicht vermeiden lässt, weil der code dadurch (wie du gleich sehen wirst) automatisch und unvermeidlich komisch wird, aber weil du es bist. 😉

    Selten so einen dummen Scheiß gelesen.
    Sollen das Makro da und die Formel Erziehungsversuche sein?
    Sei doch so fair und übersetze dein vector-Programm einigermaßen unverfälscht in ein Array-Programm.
    So zum Beispiel:

    #include <iostream>
    #include <vector>
    using namespace std;
    
    template<typename T,size_t size>
    T* begin(T (&arr)[size])
    {
        return &arr[0];
    }
    
    template<typename T,size_t size>
    T* end(T (&arr)[size])
    {
        return &arr[size];
    }
    
    int main()
    {
        int kaufbetrag, gezahlt;
        cout << "Bitte geben Sie den den Kaufbetrag in Cent ein: " << endl;
        cin >> kaufbetrag;
        cout << "Bitte geben Sie den Gezahlten Betrag in Cent ein: " << endl;
        cin >> gezahlt;
    
        int wechselgeld( gezahlt - kaufbetrag );
        if ( wechselgeld < 0 )
        {
            cout << "zu wenig, cu" << endl;
            return 1;
        }
        if ( wechselgeld == 0 )
        {
            cout << "passt, cu" << endl;
            return 0;
        }
    
        int geldEinheiten[15]={
            50000,20000,10000,
            5000,2000,1000,
            500,200,100,
            50,20,10,
            5,2,1,
            };
    
        cout << "Im Wechselgeld sind:" << endl;
        for ( int* it(begin(geldEinheiten)); it != end(geldEinheiten); ++it )
        {
            int anzahl( 0 );
            while ( *it <= wechselgeld )
            {
                ++anzahl;
                wechselgeld -= *it;
            }
            cout << anzahl << " Gegenstaende, die einen Wert von " << *it << " Cent repräsentieren." << endl;
        }
        return 0;
    }
    

    Und, welches ist hübscher?


  • Mod

    volkard schrieb:

    Und, welches ist hübscher?

    Dann musst du aber fairerweise jetzt auch ein von dir geschriebenes STL-Containerprogramm dagegen setzen, bei dem du dir die gleiche Mühe gibst. Vorzugsweise mit C++0x-Initialisierungslisten.



  • volkard schrieb:

    Selten so einen dummen Scheiß gelesen.
    Sollen das Makro da und die Formel Erziehungsversuche sein?
    Sei doch so fair und übersetze dein vector-Programm einigermaßen unverfälscht in ein Array-Programm.

    Sollte eigentlich nur Spaß sein, gute Güte. :p

    volkard schrieb:

    Und, welches ist hübscher?

    Natürlich deins, was für ne Frage.

    Edit: Da der Zwinkersmiley im Post vorhin nicht gereicht hat, versuch ich, durch etwas mehr Persönlichkeit zu versöhnen. 😉
    http://i54.tinypic.com/29zrn6v.jpg
    PS: Serotonin! Es sonnt doch. 🙂



  • Darf ich auch meckern? 😃

    Ich finde direct initialization da, wo copy initialization gereicht hätte, hässlich. Mir läuft da immer ein Schauer über den Rücken, wenn ich so etwas lese.

    int i( 14 ); // direct initialization
    int j = 15;  // copy initialization
    

    Lasst Euch von den Namen doch nicht durcheinander bringen. DI ist jetzt nicht "schneller", weil's "direct" ist. Da kommt bei (wahrscheinlich) allen Compiler eh der gleiche Code bei raus.

    Ein statisches, konstantes Array hier als Lookup-Tabelle ist jetzt auch keine ganz so schlechte Idee.

    Bzgl Minimale Anzahl von Münzen/Scheinen, fällt mir noch Backtracking ein. Aber das ist bei diesen Münz/Schein-Werten überflüssig. Bei anderen "komischen" Münzwerten müsste man dann die Lösung anders finden. Beispiel:
    Münzen im Wert von 50, 40, 30, 5 Cent. Betrag: 70 Cent
    70 = 50 + 5 + 5 + 5 + 5 (ist aber offensichtlich nicht optimal!)
    70 = 40 + 30 (optimal)



  • krümelkacker schrieb:

    Darf ich auch meckern? 😃

    Ich finde direct initialization da, wo copy initialization gereicht hätte, hässlich. Mir läuft da immer ein Schauer über den Rücken, wenn ich so etwas lese.

    int i( 14 ); // direct initialization
    int j = 15;  // copy initialization
    

    Lasst Euch von den Namen doch nicht durcheinander bringen. DI ist jetzt nicht "schneller", weil's "direct" ist. Da kommt bei (wahrscheinlich) allen Compiler eh der gleiche Code bei raus.

    Klar darfste meckern. 🙂
    Dass bei Zuweisung an einer Deklaration nicht der Zuweisungsoperator benutzt wird, weiß ich. Ich find "int i( 14 );" aber irgendwie intuitiver als "int i = 14;", weil man dann diesen "Tweak" in der Sprache gar nicht bedenken muss.



  • Dobi schrieb:

    krümelkacker schrieb:

    Darf ich auch meckern? 😃

    Ich finde direct initialization da, wo copy initialization gereicht hätte, hässlich. Mir läuft da immer ein Schauer über den Rücken, wenn ich so etwas lese.

    int i( 14 ); // direct initialization
    int j = 15;  // copy initialization
    

    Lasst Euch von den Namen doch nicht durcheinander bringen. DI ist jetzt nicht "schneller", weil's "direct" ist. Da kommt bei (wahrscheinlich) allen Compiler eh der gleiche Code bei raus.

    Klar darfste meckern. 🙂
    Dass bei Zuweisung an einer Deklaration nicht der Zuweisungsoperator benutzt wird, weiß ich. Ich find "int i( 14 );" aber irgendwie intuitiver als "int i = 14;", weil man dann diesen "Tweak" in der Sprache gar nicht bedenken muss.

    Ob da der Zuweisungsoperator genutzt wird oder nicht, ist hier gar nicht die Frage, das sollte ja wohl klar sein, da es eine Initialisierung ist und keine Zuweisung. Es ging um Direct-Initialization oder Copy-Initialization 😉

    Lg freeG

    Lg freeG



  • fr33g schrieb:

    Ob da der Zuweisungsoperator genutzt wird oder nicht, ist hier gar nicht die Frage, das sollte ja wohl klar sein, da es eine Initialisierung ist und keine Zuweisung. Es ging um Direct-Initialization oder Copy-Initialization 😉

    Weiß er ja, hat er ja auch geschrieben dass er das weiß.
    Ob so oder so ist Jacke wie Hose. Es macht das selbe, und ob es jetzt ein "tweak" in der Sprache ist oder nicht, ist auch wurscht, weils beides gängige Praxis ist. Man sollte beides lesen können ohne drüber zu stolpern. Es ist eine reine Geschmacksfrage, welche Form man vorzieht.



  • pumuckl schrieb:

    fr33g schrieb:

    Ob da der Zuweisungsoperator genutzt wird oder nicht, ist hier gar nicht die Frage, das sollte ja wohl klar sein, da es eine Initialisierung ist und keine Zuweisung. Es ging um Direct-Initialization oder Copy-Initialization 😉

    Weiß er ja, hat er ja auch geschrieben dass er das weiß.
    Ob so oder so ist Jacke wie Hose. Es macht das selbe, und ob es jetzt ein "tweak" in der Sprache ist oder nicht, ist auch wurscht, weils beides gängige Praxis ist. Man sollte beides lesen können ohne drüber zu stolpern. Es ist eine reine Geschmacksfrage, welche Form man vorzieht.

    Ich weiß ja dass er das weiß. Aber krümelkacker meinte ja den Unterschied zwischen Copy-Initialization und Direct-Initialization, den es oft gar nicht gibt. Und ich habe es dann so verstanden, als wie Dobi das gar nicht gemerkt hat, sondern dachte, Krümelkacker meinte das mit dem Zuweisungsoperator. Aber darum ging es ja Krümelkacker nicht.
    Aber is ja jetzt auch Wurscht 😋

    Lg freeG



  • Nee, ist ne reine Geschmacksfrage (in den meisten Fällen). Meine Präferenz habe ich kund getan (CI). Für mich sieht DI zu sehr nach einer Funktionsdeklaration aus. In C schreibt das ja auch keiner so auf.

    Ich wollte nur nicht, dass einer denkt, dass DI irgendwie effizienter sei als CI und es nur deswegen verwendet.


Anmelden zum Antworten