web-dev-qa-db-fra.com

Comment échanger deux nombres sans utiliser de variables temporaires ou d'opérations arithmétiques?

Cette équation échange deux nombres sans variable temporaire, mais utilise des opérations arithmétiques:

a = (a+b) - (b=a);

Comment puis-je le faire sans opérations arithmétiques? Je pensais à XOR.

31
mr_eclair
a=a+b;
b=a-b;
a=a-b;

C'est simple mais efficace ....

21
sreejith k s

Pourquoi ne pas utiliser les libs std?

std::swap(a,b);
18
Martin York

En C cela devrait fonctionner:

a = a^b;
b = a^b;
a = a^b;

OU un cooler/geekier à la recherche:

a^=b;
b^=a;
a^=b;

Pour plus de détails, regardez dans this . XOR est une opération très puissante qui a de nombreux usages intéressants ici et là.

16
BiGYaN

Le meilleur moyen d'échanger deux nombres sans utiliser d'opération arithmétique ou de stockage temporaire est de charger les deux variables dans des registres, puis d'utiliser les registres à l'envers!

Vous ne pouvez pas le faire directement à partir de C, mais le compilateur est probablement tout à fait capable de le résoudre pour vous (du moins si l'optimisation est activée) - si vous écrivez un code simple et évident, tel que celui suggéré par KennyTM .

par exemple.

void swap_tmp(unsigned int *p)
{
  unsigned int tmp;

  tmp = p[0];
  p[0] = p[1];
  p[1] = tmp;
}

compilé avec gcc 4.3.2 avec l'indicateur d'optimisation -O2 donne:

swap_tmp:
        pushl   %ebp               ;  (prologue)
        movl    %esp, %ebp         ;  (prologue)
        movl    8(%ebp), %eax      ; EAX = p
        movl    (%eax), %ecx       ; ECX = p[0]
        movl    4(%eax), %edx      ; EDX = p[1]
        movl    %ecx, 4(%eax)      ; p[1] = ECX
        movl    %edx, (%eax)       ; p[0] = EDX
        popl    %ebp               ;  (epilogue)
        ret                        ;  (epilogue)
14
Matthew Slattery

Je n'avais jamais vu cette solution C auparavant, mais je suis sûr que quelqu'un y a pensé. Et peut-être eu plus de maîtrise de soi que moi.

fprintf(fopen("temp.txt", "w"), "%d", a);
a = b;
fscanf(fopen("temp.txt", "r"), "%d", &b);

Aucune variable supplémentaire!

Cela fonctionne pour moi, mais en fonction de l'implémentation de stdio, vous devrez peut-être faire quelque chose pour mettre en mémoire tampon la sortie.

5

a = ((a = a + b) - (b = a - b));

4
Syed Raza Mehdi

En utilisant XOR,

void swap(int &a, int &b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

Une doublure avec XOR,

void swap(int &a, int &b)
{
    a ^= b ^= a ^= b;
}

Ces méthodes semblent être propres, car elles n'échouent pas pour tous les cas de test, mais encore une fois, puisque (comme dans la méthode 2), la valeur de variable est modifiée deux fois dans le même point de séquence. On dit qu'elle a un comportement indéfini déclaré par ANSI C.

3
Shubham A.

C++11 permet de:

  • Valeurs d'échange :

    std::swap(a, b);
    
  • plages d'échange :

    std::swap_ranges(a.begin(), a.end(), b.begin());
    
  • Créer LValue Tuple avec tie :

    std::tie(b, a) = std::make_Tuple(a, b);
    
    std::tie(c, b, a) = std::make_Tuple(a, b, c);
    
1
k06a

Solution simple dont je me souviens de mes célibataires :-)

a = a+b-(b=a);

 Example

0
Reddy

La multiplication et la division peuvent également être utilisées. 

 int x = 10, y = 5;

 // Code to swap 'x' and 'y'
 x = x * y;  // x now becomes 50
 y = x / y;  // y becomes 10
 x = x / y;  // x becomes 5
0
Moiz Sajid

Outre les solutions ci-dessus dans le cas où, si l'une des valeurs est hors limites pour un entier signé, les valeurs des deux variables peuvent être permutées de cette manière.

a = a+b;
b=b-(-a);
a=b-a;
b=-(b);
0
Khushi