Wie kehre ich programmatisch die max zweier ganzer Zahlen ohne Vergleichsoperatoren mit und ohne Verwendung von if, else, etc?

StackOverflow https://stackoverflow.com/questions/227383

Frage

Wie kann ich das Maximum von zwei ganzen Zahlen programmatisch zurückzukehren, ohne Vergleichsoperatoren mit und ohne Verwendung von if, else, etc?

War es hilfreich?

Lösung

max: // Wird setzen MAX (a, b) in a

a -= b;
a &= (~a) >> 31;
a += b;

Und:

int a, b;

min: // Wird gesetzt MIN (a, b) in a

a -= b;
a &= a >> 31;
a += b;

hier .

Andere Tipps

http://www.graphics.stanford.edu/~seander /bithacks.html#IntegerMinOrMax

r = x - ((x - y) & -(x < y)); // max(x, y)

Sie können Spaß haben mit arithmetisch Verschiebung (x - y) das Vorzeichenbit zu sättigen, aber dies ist in der Regel genug. Oder Sie können den High-Bit testen, immer Spaß.

Ich glaube, ich habe es.

int data[2] = {a,b};
int c = a - b;
return data[(int)((c & 0x80000000) >> 31)];

Wäre das nicht? Grundsätzlich nehmen Sie den Unterschied der beiden, und dann wieder die eine oder andere basierend auf dem Vorzeichen-Bit. (Dies ist, wie der Prozessor tut größer oder kleiner ist als ohnehin.) Also, wenn das Vorzeichenbit 0 ist, kehrt ein, da ein größer oder gleich b. Wenn der Vorzeichen-Bit 1 ist, kehrt b, weil Subtrahieren b von einem verursachte das Ergebnis negativ zu werden, was darauf hinweist, dass b größer als a. So stellen Sie sicher, dass Ihre Ints sind 32bits unterzeichnet.

In der Mathematik Welt:

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

Neben mathematisch korrekt ist, es ist nicht Annahmen über die Bitgröße als Verschiebeoperationen tun müssen, um zu machen.

|x| steht für den absoluten Wert von x.

Kommentar:

Sie haben Recht, wurde der absolute Wert vergessen. Dies sollte für alle a, b positiv oder negativ gelten

return (a> b a: b);

oder

int max(int a, int b)
{
        int x = (a - b) >> 31;
        int y = ~x;
        return (y & a) | (x & b); 
}

nicht so pfiffige wie oben ... aber ...

int getMax(int a, int b)
{
    for(int i=0; (i<a) || (i<b); i++) { }
    return i;
}

Da dies ein Rätsel ist, wird Lösung leicht gefaltet werden:

let greater x y = signum (1+signum (x-y))

let max a b = (greater a b)*a + (greater b a)*b

Dies ist Haskell, aber es wird das gleiche in einer anderen Sprache sein. C / C # Leute sollten "sgn" (oder "Zeichen"?) Anstelle von signum verwenden.

Beachten Sie, dass dies auf Ints beliebiger Größe arbeiten und auf reelle Zahlen als gut.

Von Z0MBIE der (bekannten virii Drehbuch) Artikel "Polymorphe Games", vielleicht finden Sie es nützlich:

#define H0(x)       (((signed)(x)) >> (sizeof((signed)(x))*8-1))
#define H1(a,b)     H0((a)-(b))

#define MIN1(a,b)   ((a)+(H1(b,a) & ((b)-(a))))
#define MIN2(a,b)   ((a)-(H1(b,a) & ((a)-(b))))
#define MIN3(a,b)   ((b)-(H1(a,b) & ((b)-(a))))
#define MIN4(a,b)   ((b)+(H1(a,b) & ((a)-(b))))
//#define MIN5(a,b)   ((a)<(b)?(a):(b))
//#define MIN6(a,b)   ((a)>(b)?(b):(a))
//#define MIN7(a,b)   ((b)>(a)?(a):(b))
//#define MIN8(a,b)   ((b)<(a)?(b):(a))

#define MAX1(a,b)   ((a)+(H1(a,b) & ((b)-(a))))
#define MAX2(a,b)   ((a)-(H1(a,b) & ((a)-(b))))
#define MAX3(a,b)   ((b)-(H1(b,a) & ((b)-(a))))
#define MAX4(a,b)   ((b)+(H1(b,a) & ((a)-(b))))
//#define MAX5(a,b)   ((a)<(b)?(b):(a))
//#define MAX6(a,b)   ((a)>(b)?(a):(b))
//#define MAX7(a,b)   ((b)>(a)?(b):(a))
//#define MAX8(a,b)   ((b)<(a)?(a):(b))

#define ABS1(a)     (((a)^H0(a))-H0(a))
//#define ABS2(a)     ((a)>0?(a):-(a))
//#define ABS3(a)     ((a)>=0?(a):-(a))
//#define ABS4(a)     ((a)<0?-(a):(a))
//#define ABS5(a)     ((a)<=0?-(a):(a))

cheers

Dies ist eine Art von Betrug, Assembler-Sprache verwenden, aber es ist trotzdem interessant:


// GCC inline assembly
int max(int a, int b)
{
  __asm__("movl %0, %%eax\n\t"   // %eax = a
          "cmpl %%eax, %1\n\t"   // compare a to b
          "cmovg %1, %%eax"      // %eax = b if b>a
         :: "r"(a), "r"(b));
}

Wenn Sie über die Regeln zu streng sein wollen und sagen, dass die cmpl Anweisung für diese illegal ist, dann ist die folgende (weniger effizient) Sequenz funktioniert:


int max(int a, int b)
{
  __asm__("movl %0, %%eax\n\t"
      "subl %1, %%eax\n\t"
          "cmovge %0, %%eax\n\t"
          "cmovl %1, %%eax"
         :: "r"(a), "r"(b)
         :"%eax");
}
int max(int a, int b)
{
   return ((a - b) >> 31) ? b : a;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top