Sortieren Sie 3 Zahlen ohne Verwendung von logischen Operatoren.



  • Ich hätt das jetzt von der anderen Seite aufgezogen. Beispielsweise

    #include <iostream>
    
    int main() {
      int a, b, c;
    
      std::cin >> a >> b >> c;
    
      int kleinstes = a;
      int groesstes = a;
    
      if(b < kleinstes) { kleinstes = b; }
      if(c < kleinstes) { kleinstes = c; }
    
      if(b > groesstes) { groesstes = b; }
      if(c > groesstes) { groesstes = c; }
    
      int mitte = a + b + c - kleinstes - groesstes;
    
      std::cout << kleinstes << " <= " << mitte << " <= " << groesstes;
    }
    

    ...wobei das mit Funktionen (min, max bspw.) natürlich noch hübscher geht.



  • Das lässt sich mit einem Sortiernetz lösen (hier Bubblesort) - angenommen, std::swap ist erlaubt 😃

    #include <iostream>
    #include <algorithm>
    
    int main()
    {
            int a, b, c;
            std::cin >> a >> b >> c;
    
            if(a < b) std::swap(a, b);
            if(b < c) std::swap(b, c);
            if(a < b) std::swap(a, b);
    
            std::cout << a << ", " << b << ", " << c;
    }
    

    .



  • max(a,b) = (|a+b| + |a-b|)/2;
    min(a,b) = (|a+b| - |a-b|)/2
    

    Alles andere ist nur eine geschachtelte Anwendung von min/max. Weitrauming kann if auch als Vergleichsoperator aufgefasst werden.



  • Wollte wissen, ob man die Aufgabe auch ohne logische Op. (incl. Vergleichsoperatoren), ohne ifs, ohne swaps, etc. lösen kann. Gerade eben habe ich gesehen, dass knivils Lösung auch in die Richtung geht, ist aber eleganter. Schade um die Zeit, aber was soll's.

    #include<iostream>
    
    int max (int x, int y)
    {
    	return x * bool(int(x / y)) + y * bool(int(y / x)) * (bool (x-y));
    }
    
    int min (int x, int y)
    {
    	return y * bool(int(x / y)) + x * bool(int(y / x)) * (bool (x-y));
    }
    
    int main()
    {
    	int a, b, c;
    	std::cin >> a >> b >> c; 
    	int sum = a + b + c;
    
    	int smallest = min (min(a, b), min(b, c));
    	int largest = max (max(a, b), max(b, c));
    	int mid = sum - smallest - largest;
    
    	std::cout << smallest << ' ' << mid << ' ' << largest;
    }
    

    Edit: hatte die Summe vergessen.


  • Mod

    Der Cast zu bool ist aber auch nur ein gut versteckter Vergleich 🕶



  • "Betrag" ist ein verstecktes "if", genau so wie "cast nach bool" eines ist.
    Ich sehe keinen besonderen Sinn dahinter eines von beiden zu akzeptieren und gleichzeitig einen einfachen Vergleich zu verbieten.

    @knivil
    Zeig mal wie du "Betrag von" in C++ ohne if und ohne eine Funktion aufzurufen machen willst.

    @[Rewind]
    Bei x==y kommt bei dir 0 raus würde ich sagen. Und mit negativen Zahlen wird das auch nicht funktionieren.

    So wäre mal die Sache mit x==y gelöst:

    int max (int x, int y)
    {
        return x * bool(int(x / y)) + y * bool(int(y / (x+1)));
    }
    

    Negative Zahlen gehen immer noch nicht, und x darf jetzt nimmer INT_MAX sein.
    Aber naja, wie gesagt mMn. immer noch ziemlich sinnfrei, von daher...


  • Mod

    hustbaer schrieb:

    "Betrag" ist ein verstecktes "if", genau so wie "cast nach bool" eines ist.

    Für den Betrag gibt es Bittricks:
    http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs

    Ist jetzt natürlich die Frage, ob man bitweise Operationen als logische Operationen ansieht. Ich würde es nicht tun. Sie sind eher Rechenoperationen wie Addition.

    edit: Im Absatz unter dem verlinkten stehen dann auch gleich min und max ohne logische Operatoren ausgeschrieben:

    r = y + ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // min(x, y)
    r = x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // max(x, y)
    


  • hustbaer schrieb:

    @[Rewind]
    Bei x==y kommt bei dir 0 raus würde ich sagen.

    Würde ich nicht sagen. Genau aus diesem Grund multipliziere ich am Ende noch mit der Differenz der beiden Zahlen.

    hustbaer schrieb:

    Und mit negativen Zahlen wird das auch nicht funktionieren.

    Jein. Es gibt, glaube ich, nur einen Fall, wo das nicht funktioniert, und zwar wenn x + y = 0 .



  • Der Betrag im ersten Term kann weggelassen werden, dann sollte es auch fuer negative Zahlen funktionieren.

    max(a,b) = (a+b + |a-b|)/2;
    min(a,b) = (a+b - |a-b|)/2
    

    Um den Absolutwert auszurechnen, kann das Sign-Bit pauschal auf 0 gesetzt werden. Spielchen mit Zweierkomplement sind auch moeglich.



  • Sone schrieb:

    Ich stelle mich nicht doof! Was soll er denn sonst darunter meinen, da fällt mir echt nichts ein 😞

    < ist aber kein logischer, sondern ein relationaler Operator.



  • Tachyon schrieb:

    Sone schrieb:

    Ich stelle mich nicht doof! Was soll er denn sonst darunter meinen, da fällt mir echt nichts ein 😞

    < ist aber kein logischer, sondern ein relationaler Operator.

    Wenn das so ist, dann erzählt deutsches Wiki mal wieder Schrott 😡



  • out schrieb:

    Tachyon schrieb:

    Sone schrieb:

    Ich stelle mich nicht doof! Was soll er denn sonst darunter meinen, da fällt mir echt nichts ein 😞

    < ist aber kein logischer, sondern ein relationaler Operator.

    Wenn das so ist, dann erzählt deutsches Wiki mal wieder Schrott 😡

    Ist aber so. Logische Operatoren haben typischerweise Wahrheitswerte als Operanden. Die englische Wikiseite hat eine korrekte Auflistung.



  • Hä? Logische Operatoren sind einfach nur Operatoren, die einen Wahrheitswert liefern. Und darunter fallen halt auch relationale Operatoren.

    < ist also ein logischer Operator. Speziell halt nur ein relationaler.



  • Incocnito schrieb:

    Logische Operatoren sind einfach nur Operatoren, die einen Wahrheitswert liefern.

    Nein, logische Operatoren modellieren Verknüpfungen der Aussagenlogik. In C++ wären das Konjunktion (Und), Disjunktion (Oder) und Negation (Nicht).



  • out schrieb:

    Tachyon schrieb:

    Sone schrieb:

    Ich stelle mich nicht doof! Was soll er denn sonst darunter meinen, da fällt mir echt nichts ein 😞

    < ist aber kein logischer, sondern ein relationaler Operator.

    Wenn das so ist, dann erzählt deutsches Wiki mal wieder Schrott 😡

    Seit wann gibt man was auf Wikipedia wenn die Infos wirklich richtig sein sollen?



  • Achso, jetzt hab ichs auch gecheckt.
    Dann muss also nur die Zeile "Vergleiche" aus der Tabelle in dem Artikel entfernt werden (de.wikipedia.org/wiki/Logischer_Operator).



  • [Rewind] schrieb:

    hustbaer schrieb:

    @[Rewind]
    Bei x==y kommt bei dir 0 raus würde ich sagen.

    Würde ich nicht sagen. Genau aus diesem Grund multipliziere ich am Ende noch mit der Differenz der beiden Zahlen.

    Argh - ich hab mir da einer Klammer eingebildet die gar nicht da ist - es wird ja nur der y * ... Teil mit bool(x-y) multipliziert, nicht die Summe. Ja, dann geht das natürlich.

    [Rewind] schrieb:

    hustbaer schrieb:

    Und mit negativen Zahlen wird das auch nicht funktionieren.

    Jein. Es gibt, glaube ich, nur einen Fall, wo das nicht funktioniert, und zwar wenn x + y = 0 .

    Entweder ich stehe schon wieder auf dem Schlauch, oder...
    Beispiel:
    x = -10
    y = 1

    max(x,y) = x * bool(int(x / y)) + y * bool(int(y / x)) * (bool (x-y));
    = -10 * bool(-10/1) + 1 * bool(1/-10) * bool(-10-1)
    = -10 * 1 + 1 * 0 * 1
    = -10
    = falsch
    


  • SeppJ schrieb:

    hustbaer schrieb:

    "Betrag" ist ein verstecktes "if", genau so wie "cast nach bool" eines ist.

    Für den Betrag gibt es Bittricks:
    http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs

    Ist mir schon klar, ich kenne die Seite.

    Ist jetzt natürlich die Frage, ob man bitweise Operationen als logische Operationen ansieht. Ich würde es nicht tun. Sie sind eher Rechenoperationen wie Addition.

    Naja man kann die als Rechenoperationen sehen. Man kann logische Operationen aber auch als Rechenoperationen auf einem beschränkten Alphabet sehen.
    Ich sehe hier die bitweisen Operationen eher als SIMD Variante der logischen Operationen.



  • hustbaer schrieb:

    ...

    So ein Mist! Du hast recht wege den neg. Zahlen. Muss mir was überlegen.



  • Negative Zahlen sind doch kein Problem. Einfach INT_MIN subtrahieren und als unsigned darstellen. Dann sortieren und am Schluss wieder jeweils INT_MIN addieren.


Anmelden zum Antworten