eine gerade oder ungerade Zahl unterscheiden



  • Hallo, hab schon überall nach der Lösung gesucht und so auf dieses schönes Forum gestoßen. Ich hab eine Aufgabenstellung wo es bei einer geraden Zahl eine Formel und bei einer ungeraden Zahl eine andere Formel ausgeführt werden soll. Nun suche ich vergeblich nach einer Methode das Programm zwischen geraden und ungeraden Zahlen unterscheiden zu lassen. Wie macht man sowas? Danke 🙂



  • Kennst du die Modulo-Operation, schau sie dir mal an. Und dann überleg dir, wie eine gerade Zahl definiert ist. 🙂



  • bool isEven(int number)
    {
      return number % 2 == 0;
    }
    

    Edit: Haha, immerhin noch zweiter. 🤡



  • Das macht man ueber den Modulo-Operator. a mod b berechnet den Rest der Division von a / b. Wenn a mod 2 = 0, dann ist die Zahl gerade und sonst nicht.

    In C++:

    int main()
    {
    	int a = 5;
    
    	if ( a % 2 == 0 )
    		cout << "Gerade" << endl;
    	else
    		cout << "Ungerade" << endl;
    }
    

    Dabei ist % der Modulo-Operator.



  • int main()
    {
      int zahl = 24789243;
      bool gerade =  (zahl % 2) == 0;
      if(gerade)
      {
        foo();
      }
      else
      {
         bar();
      }
    }
    

    Edit: Mist, zu spät...



  • vielen dank euch Leute! jetzt ist es klar) 👍 🙂



  • Warum nicht

    bool isEven(int number)
    {
      return !(number & 1);
    }
    

    Kostet weitaus weniger als ein Modulo.



  • Hmmh schrieb:

    Warum nicht

    bool isEven(int number)
    {
      return !(number & 1);
    }
    

    Kostet weitaus weniger als ein Modulo.

    In den meisten Faellen duerfte das nicht wirklich einen grossen Performaceunterschied ergeben.
    Da ist der Rechner schon schnell genug.



  • Hmmh schrieb:

    Warum nicht

    bool isEven(int number)
    {
      return !(number & 1);
    }
    

    Kostet weitaus weniger als ein Modulo.

    Das optimiert der Compiler schon. Der Modulooperator ist hier verständlicher.



  • ipsec schrieb:

    Das optimiert der Compiler schon. Der Modulooperator ist hier verständlicher.

    Tut er nicht. MSVC:

    if (isEven(i))
    012216CA  mov         ecx,dword ptr [esp+4]  
    012216CE  and         ecx,80000001h  
    012216D4  jns         main+2Bh (12216DBh)  
    012216D6  dec         ecx  
    012216D7  or          ecx,0FFFFFFFEh  
    012216DA  inc         ecx  
    012216DB  jne         main+3Ch (12216ECh)
    

    VS

    if (isEven(i))
    003516CA  mov         cl,byte ptr [esp+4]  
    003516CE  not         cl  
    003516D0  test        cl,1  
    003516D3  je          main+34h (3516E4h)
    

    Hat mich auch überrascht. Ich frage mich, ob irgendeine Regel im Standard verhindert, dass hier optimiert werden darf.



  • Da war einer schneller, ich wollte auch gerade asm-Output posten (auch MSVC).

    Natürlich sind dies Mikrooptimierungen, aber das Thema Verständlichkeit gilt hier nicht, wenn der Code in einer kleinen Funktion mit aussagekräftigem Namen steht.



  • cooky451 schrieb:

    ipsec schrieb:

    Das optimiert der Compiler schon. Der Modulooperator ist hier verständlicher.

    Tut er nicht. MSVC:

    if (isEven(i))
    012216CA  mov         ecx,dword ptr [esp+4]  
    012216CE  and         ecx,80000001h  
    012216D4  jns         main+2Bh (12216DBh)  
    012216D6  dec         ecx  
    012216D7  or          ecx,0FFFFFFFEh  
    012216DA  inc         ecx  
    012216DB  jne         main+3Ch (12216ECh)
    

    VS

    if (isEven(i))
    003516CA  mov         cl,byte ptr [esp+4]  
    003516CE  not         cl  
    003516D0  test        cl,1  
    003516D3  je          main+34h (3516E4h)
    

    Hat mich auch überrascht. Ich frage mich, ob irgendeine Regel im Standard verhindert, dass hier optimiert werden darf.

    Was kommt denn raus, wenn Du den Test nochmal mit unsigned int machst und als den Zielprozessor was modernes einstellst?



  • volkard schrieb:

    Was kommt denn raus, wenn Du den Test nochmal mit unsigned int machst und als den Zielprozessor was modernes einstellst?

    Gut erkannt, mit unsigned geht es. [Edit: Das könnte bedeuten, dass AND nicht so definiert ist, dass es als Lösung immer genügt. Wobei das für übliche Systeme wohl egal sein dürfte.]

    http://en.wikipedia.org/wiki/Signed_number_representations#Comparison_table
    Interessant, dass es bei negativen ungeraden Zahlen auch die Möglichkeit gibt, ein 0 bit am Ende zu haben. Die Frage ist, wie weit der Standard hier definiert. Soweit ich mich erinnern kann, lässt er es offen, was tatsächlich bedeuten würde, dass die !(i & 1)-Methode nicht immer funktionieren muss.



  • Das ist, damit er bei -1 % 2 == -1 haben kann. Ich versteh nur nicht, was das soll. Das Verhalten für negative Operanden schreibt der Standard nicht vor, er lässt es offen. Es ist außerdem unpraktisch und nicht mit dem Gebrauch von Modulo in der Mathematik konform.



  • Bashar schrieb:

    Das ist, damit er bei -1 % 2 == -1 haben kann. Ich versteh nur nicht, was das soll. Das Verhalten für negative Operanden schreibt der Standard nicht vor, er lässt es offen. Es ist außerdem unpraktisch und nicht mit dem Gebrauch von Modulo in der Mathematik konform.

    Aber wegen -1/2=0 will man es wieder, sagte irgend jemand mir irgendwann irgendwo.
    Damit man aus a/b und a%b wieder a basteln kann. a=(a/b)*b + (a%b).


  • Mod

    Bashar schrieb:

    Das ist, damit er bei -1 % 2 == -1 haben kann. Ich versteh nur nicht, was das soll. Das Verhalten für negative Operanden schreibt der Standard nicht vor, er lässt es offen. Es ist außerdem unpraktisch und nicht mit dem Gebrauch von Modulo in der Mathematik konform.

    Im neuen Standard besteht keine Wahl mehr.

    n3290 schrieb:

    5.6/4 The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. For integral operands the / operator yields the algebraic quotient with any fractional part discarded;81 if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a.



  • camper schrieb:

    Bashar schrieb:

    Das ist, damit er bei -1 % 2 == -1 haben kann. Ich versteh nur nicht, was das soll. Das Verhalten für negative Operanden schreibt der Standard nicht vor, er lässt es offen. Es ist außerdem unpraktisch und nicht mit dem Gebrauch von Modulo in der Mathematik konform.

    Im neuen Standard besteht keine Wahl mehr.

    n3290 schrieb:

    5.6/4 The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. For integral operands the / operator yields the algebraic quotient with any fractional part discarded;81 if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a.

    Die Wahl wäre, daß gegen -inf gerundet wird und nicht gegen 0, wenn Zahlen dividiert werden.
    Also -7/2=-4. Oder?


  • Mod

    volkard schrieb:

    camper schrieb:

    Bashar schrieb:

    Das ist, damit er bei -1 % 2 == -1 haben kann. Ich versteh nur nicht, was das soll. Das Verhalten für negative Operanden schreibt der Standard nicht vor, er lässt es offen. Es ist außerdem unpraktisch und nicht mit dem Gebrauch von Modulo in der Mathematik konform.

    Im neuen Standard besteht keine Wahl mehr.

    n3290 schrieb:

    5.6/4 The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. For integral operands the / operator yields the algebraic quotient with any fractional part discarded;81 if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a.

    Die Wahl wäre, daß gegen -inf gerundet wird und nicht gegen 0, wenn negative Zahlen dividiert werden.
    Also -7/2=-4. Oder?

    Genau. Das ist jetzt nicht mehr konform.



  • Und dabei haste den Part sogar noch hervorgehoben. Sorry.



  • Oh, das ist schon in C99 so und wurde wohl nachgezogen. Man sollte dann aber IMHO nicht mehr von "Modulo-Operator" sprechen, das ist jetzt der "Rest-Operator".

    Hier gibts eine schöne Tabelle, in welchen Programmiersprachen es Modulo- und Rest-Operatoren gibt:
    http://en.wikipedia.org/wiki/Modulo_operation

    Die meisten, die beides haben, nennen den einen mod und den anderen rem. Unser % ist rem.


Anmelden zum Antworten