Comment est-ce que je retourne par programme le maximum de deux entiers sans utiliser d'opérateurs de comparaison et sans utiliser if, else, etc.?

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

Question

Comment renvoyer par programme le maximum de deux entiers sans utiliser d'opérateur de comparaison ni si , sinon , etc.?

Était-ce utile?

La solution

max: // mettra MAX (a, b) dans un

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

Et:

int a, b;

min: // mettra MIN (a, b) dans un

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

from ici .

Autres conseils

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

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

Vous pouvez vous amuser avec un décalage arithmétique de (x - y) pour saturer le bit de signe, mais cela suffit généralement. Ou vous pouvez tester le bit fort, toujours amusant.

Je pense que je l'ai.

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

Cela ne fonctionnerait-il pas? Fondamentalement, vous prenez la différence des deux, puis vous retournez l’un ou l’autre en fonction du bit de signe. (C'est ainsi que le processeur fait plus que ou moins que de toute façon.) Donc, si le bit de signe est 0, retourne a, puisque a est supérieur ou égal à b. Si le bit de signe est 1, renvoyer b, car soustraire b de a a rendu le résultat négatif, indiquant que b était supérieur à a. Assurez-vous simplement que vos ints sont signés 32bits.

Dans le monde des mathématiques:

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

Hormis être mathématiquement corrects, il ne faut pas présumer de la taille des bits, contrairement aux opérations de décalage.

| x | représente la valeur absolue de x.

Commentaire:

Vous avez raison, la valeur absolue a été oubliée. Cela devrait être valable pour tout a, b positif ou négatif

retour (a > b? a: b);

ou

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

pas aussi chic que ci-dessus ... mais ...

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

S'agissant d'un casse-tête, la solution sera légèrement compliquée:

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

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

C’est Haskell, mais ce sera la même chose dans toutes les autres langues. Les utilisateurs de C / C # doivent utiliser " sgn " (ou "signe") au lieu de signum.

Notez que cela fonctionnera sur les ints de taille arbitraire et sur les réels également.

De l'article de z0mbie (célèbre auteur virii) "Jeux polymorphiques", vous le trouverez peut-être utile:

#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))

acclamations

C’est un peu une tricherie, en utilisant un langage assembleur, mais c’est quand même intéressant:


// 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));
}

Si vous voulez être strict sur les règles et dire que l'instruction cmpl est illégale pour cela, la séquence suivante (moins efficace) fonctionnera:


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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top