views:

364

answers:

5

This equation swaps two numbers without a temporary variable, but uses arithmetic operations:

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

How can I do it without arithmetic operations? I was thinking with XOR

+7  A: 

http://en.wikipedia.org/wiki/XOR_swap_algorithm

Note: Don't use this unless you absolutely have to (i.e. you are writing hyper-optimised assembler). The article gives some reasons why not.

Oli Charlesworth
wow! its awesome.. never thought of it.. :)
Idlecool
@Idlecool Now read [this part](http://en.wikipedia.org/wiki/XOR_swap_algorithm#Reasons_for_avoidance_in_practice)
Michael Mrozek
@Idlecool: my advice? Be awed by it, mention it over beers to your teammates, then **never think of it again**.
Michael Petrotta
so which method is useful .. rather than XOR
mr_eclair
Don't use this method ever. It's slower than using a temporary and ugly.
GMan
@mr_eclair: KennyTM posted a comment with the current best practice for swapping variable values. It's really quite elegant.
Michael Petrotta
Thanks you very much.. i done with XOR operation .. chk out http://codepad.org/l0CclHxG
mr_eclair
+1  A: 

In C this should work:

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

OR a cooler/geekier looking:

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

For more details look into [1]. XOR is a very powerful operation that has many interesting usages cropping up here and there.

[1] http://en.wikipedia.org/wiki/XOR_swap_algorithm

BiGYaN
@BigYan thanks for XOR .. bt XOR operation is very slower any other method to solve this problem ?
mr_eclair
@mr_eclair Let me try some other bit manipulations
BiGYaN
@mr_eclair: On any typical platform, you're not going to get any faster than KennyTM's suggestion up at the top.
Oli Charlesworth
To make it even less readable you could use the comma operator: a^=b, b^=a, a^=b;
Martin York
@mr_eclair: What do you mean it's slower? The *method* is to use a damn temporary variable. (Use `std::swap`.) That's it. What's the point of this question? Do you have an actual problem?
GMan
+1  A: 

Why not use the std libs?

std::swap(a,b);
Martin York
I think the asker wants a solution involving the lower level details here, not just calling a ready made function/library.
sandeepan
@sandeepan: It is not for me or you to interpret what the question is. We should answer the question stated with the best solution to the problem (if it is not what the OP requires then we will not get a check-mark). But I stand by this being the best solution to the question being asked (even the OP is actually playing with silly interview type questions).
Martin York
@Martin I disagree, we should interpret and understand well before answering and keep thinking whether we interpreted correctly. This question is not about an optimised/best solution, it is just about a different solution.
sandeepan
Well, the obvious reason not to use this library function would be that it doesn't work in 2/3 of the languages being asked about.
Chuck
@Chunk: 1/3 (it should work on objective-C (well objective-C++))
Martin York
@sandeeoan: The thing is I do understand the question and what he wants. But I "gave him what he needs not what he wants" and as such he should become a better developer for it.
Martin York
+2  A: 

The best way to swap two numbers without using any temporary storage or arithmetic operations is to load both variables into registers, and then use the registers the other way around!

You can't do that directly from C, but the compiler is probably quite capable of working it out for you (at least, if optimisation is enabled) - if you write simple, obvious code, such as that which KennyTM suggested in his comment.

e.g.

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

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

compiled with gcc 4.3.2 with the -O2 optimisation flag gives:

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)
Matthew Slattery
A: 

Just use something else, e.g. a variable that's not a temporary. For instance,

int main (int argc, char** argv) {
   int a = 5; int b = 6;
   argc = a; a = b; b = argc;
}

After all, the point of the question is not to show the sane way to do it (c=a;a=b;b=c). It's to show you can think out of the box, or at least copy the answer of someone else who can.

MSalters