Schwachsinniger Code für Zwischendurch



  • Hat jemand außer volkard schon meinen Denkfehler entdeckt?

    Du dachtest, du hättest funktionsfähigen C++ Code gepostet?
    😃



  • nee, viel lustiger.

    cout << (Number/2,468,024) << endl;
    

    das ding gibt nicht 2468024 aus.



  • HumeSikkins schrieb:

    Du dachtest, du hättest funktionsfähigen C++ Code gepostet?
    😃

    Du dachtest ich hätte gedacht? 🤡



  • volkard schrieb:

    cout << (Number/2,468,024) << endl;
    

    das ding gibt nicht 2468024 aus.

    *plonk*
    Logisch. 🙂



  • Und das er beschränkt ist, hat mir Volkard mal wieder eindrücklich gezeigt. Seine Lösung ist genau die Offensichtliche, deren Existenz ich vermutete, die ich aber nicht finden konnte.

    Oh. Ich dachte am anfang du würdest das ausschreiben, weil dir diese schreibweise nicht gefällt.

    Falls Geschwindigkeit nicht ganz so wichtig ist, könnte man ja auch einen string paresen. Dann hat man sowas Money("2.332.1213,12") oder so.



  • Was haltet ihr davon:

    #include <iostream>
    #include <cassert>
    using namespace std;
    
    class Number
    {
    public:
    	Number(unsigned int n) : _n(n) {}
    	Number operator()(Number i) const
    	{
    		assert(i._n <= _n);
    		return _n + i._n;
    	}
    	unsigned int operator()(unsigned int i = 0) const
    	{
    		assert(i < 1000);
    		return _n + i;
    	}
    private:
    	const unsigned int _n;
    };
    
    template <int n> class Number_temp {};
    
    template <int n>
    Number operator*(int i, Number_temp<n>)
    {
    	assert(i < 1000);
    	return n * i;
    }
    
    #define Billion   * Number_temp<1000000000>())(
    #define Million   * Number_temp<1000000>())(
    #define Thousand  * Number_temp<1000>())(
    
    int main()
    {
             // Funktioniert
    	unsigned int MyNumber1 = Number(1 Billion 20 Million 24 Thousand 123);
    	unsigned int MyNumber2 = Number(123 Million);
             // Wird als falsch erkannt:
    	unsigned int MyNumber3 = Number(50 Million 1 Billion);
             // Auch falsch
    	unsigned int MyNumber4 = Number(1 Billion 20 Million 24 Thousand 1892);
             // Auch falsch
    	unsigned int MyNumber5 = Number(1 Billion 1 Billion 24 Thousand 123);
             // Auch falsch
    	unsigned int MyNumber5 = Number(1 Billion 5950 Thousand 123);
    
    	cout << MyNumber1 << endl;
    	return 0;
    }
    

    Die Zahleneingabe ist intuitiv wie bei der reinen Makro-Variante, plus eine Fehlererkennung. 🙂
    Falsche Zahlen werden allerdings erst zur Laufzeit durch die Asserts erkannt.



  • Vielleicht geht's ja wirklich nur mir so, aber ich finde "123456789.12" ja noch übersichtlicher als "123 Milion 456 Thousand 769.12". Und da eine englische eingaber scheibar gefordert ist kann man meinen vorgeschlagenen Parser ja anpassen Money("123,456,789.12").

    Vor allem solche angaben sind doch bei euch immer noch möglich: 1 Million 5000 Thousand. Soll heißen 6 Millionen.



  • @Helium
    Die String-Variante ist in meiner Money-Klasse bereits drin. Natürlich mit wählbarem Grouping und Thousand-Seperator 😉



  • Frei nach Asterix: Die spinnen, die cpp-ler *g*



  • cd9000 schrieb:

    Was haltet ihr davon:
    unsigned int MyNumber5 = Number(1 Billion 1 Billion 24 Thousand 123);

    auch das ist meines erachtens nach zu gefährlich wegen
    unsigned int gibi1 = 1073741824;
    unsigned int gibi2 = Number(1 Billion 073 Million 741 Thousand 824);
    und der rätselhaften ausgabe von cout<<gibi2; mit 1059741824
    und wer läßt schon gerne auf solcherlei weise 14 millionen verschwinden?



  • Wer würde bei dieser Syntax schon Oktalzahlen schreiben?

    Dann kann man es auch gleich so machen:

    class Number
    {
      public: Number(const std::string&);
    };
    #define Number(n) Number("n")
    

    Und im Parser Oktalzahlen korrigieren. 😉



  • cd9000 schrieb:

    Dann kann man es auch gleich so machen:
    #define Number(n) Number("n")

    das glaube ich nicht, tim.



  • Das war natürlich Pseudo-Code. 😉



  • cd9000 schrieb:

    Das war natürlich Pseudo-Code. 😉

    jo.
    aber dein

    Und im Parser Oktalzahlen korrigieren.

    ist ne gute idee. nen eigenen präprozessor davorkloppen wäre oft fein. auch für's foreach und um den stringliteralen ne klasse zu geben.



  • Ich meinte mit "Parser" eigentlich den Konstruktor der Klasse Number. 🙄



  • Warum nicht so:

    #include <iostream>
    #include <climits>
    using namespace std;
    
    typedef unsigned int Number;
    
    // Dummy-Klasse zum Multiplizieren:
    template <Number n>
    class Number_temp {};
    
    // Dummy-Funktion zum Validieren der Template-Argumente:
    template <Number n> void ValidateInt(){}
    
    template <Number Max, Number n = 0>
    class Number_temp3
    {
    public:
    	Number_temp3() { ValidateInt<UINT_MAX / 999 * n>(); }
    
    	template <Number n2>
    	const Number operator*(Number_temp<n2>) const
    	{
    		ValidateInt<(UINT_MAX / Max) * n * n2>();
    		return n * n2;
    	}
    	operator const Number() const { return n; }
    };
    
    #define Billion  >() * Number_temp<1000000000>() + Number_temp3<999000000,
    #define Million  >() * Number_temp<   1000000>() + Number_temp3<999000,
    #define Thousand >() * Number_temp<      1000>() + Number_temp3<999,
    
    #define Number(n) static_cast<Number>( Number_temp3<UINT_MAX, n + 0>() )
    
    int main()
    {
    	// Folgende Nummern werden korrekt berechnet.
    	Number MyNumber = Number(2 Billion 999 Million 999 Thousand 999);
    	cout << MyNumber << endl;
    	cout << Number(12 Million 72 Thousand) << endl;
    
    	// Die folgenden Zeilen werden alle zur Compilezeit als fehlerhaft erkannt:
    	Number(1 Billion 43 Million 1 Million 123);
    	Number(1 Billion 1000 Million 995 Thousand 195);
    	Number(48915 Million 1 Billion);
    	Number(8050);
    	Number(1742 Million 2 Thousand);
    
    	return 0;
    }
    

    Ist evtl. kein Standard-C++, aber beim MSVC++ kommen bei fehlerhaften Zahlen Compiler-Warnungen. 🙂



  • wow der code ist super nice. 👍



  • spitze! schrieb:

    wow der code ist super nice. 👍

    Leichte verspätung, da hat jemand aber tief gegraben :>



  • mal abgesehen davon dass Präprozessor-defines alles andere als nice sind...



  • Ich bin gerad zufällig hier drüber gestolpert, als ich bei google was ganz anderes gesucht hatte und da mir eh langweilig ist:

    #include <cassert>
    
    template <typename T>
    class number
    {
    private:
        T val;
    
    	void convert_from_octal()
    	{
    		val *= 10;
    		val /= 8;
    	}
    public: 
        number(T _val = T())
    	:	val(_val)
    	{}
    
    	number operator() (number x) const
    	{
    		if(x < 100)
    			x.convert_from_octal();
    
    		assert(x < 1000);
    		return val * 1000 + x.val;
        }
    
    	operator T() const
    	{
    		return val;
    	}
    };
    
    #include <iostream>
    
    int main()
    {
    	unsigned int x = number<unsigned int> (1)(100)(010)(001);
    	assert(x == 1100010001);
    
    	std::cout << x << std::endl;
    }
    

    Ist zwar nicht ganz so schön anzusehen wie mit '\'' oder ',', aber dafür ohne hässliche makros ^^

    bb


Anmelden zum Antworten