display | more...
Ok, this is pretty simple to do, but I've found that many people think it can't be done...so here it is, in all of it's perlified glory. This takes two arguments on the command line, stores them in 2 seperate variables, then swaps them, without using a third. The print statements are not neccessary, they are only there to prove that this does indeed work.

This is applicable to most any programming language you can think of.
#!/usr/bin/perl

$a=$ARGV[0]
$b=$ARGV[1]

print "$a\n";
print "$b\n";

$a=$a+$b;
$b=$a-$b;
$a=$a-$b;

print "$a\n";
print "$b\n";

No preformatting tool was used on the above text - all mistakes, syntactical, logical, or otherwise, are mine. I also haven't tested this for x as x->+/- infinity yet, so if it doesn't work for some obscure value, tough beans. I thought it was nifty.
You can do this with two bit strings using only three XOR's. For instance, take the strings a=0010, b=1011.

a = a XOR b = 1001
b = a XOR b = 0010
a = a XOR b = 1011

It should be noted that in Perl, at least, this can be done with a single line:

($a,$b)=($b,$a);

This works because Perl tracks both sides of the assignment. It also works with more than one variable:

($a,$b,$c,$d)=($d,$a,$b,$c);

TMTOWTDI.

Warning! This trick is not so good to use for floating point numbers because of machine epsilon. For example, this (shortened) version of the above program

#!/usr/bin/perl
($a,$b)=@ARGV;
printf("%g %g\n",$a, $b);
$a=$a+$b; $b=$a-$b; $a=$a-$b;
printf("%g %g\n", $a, $b);
will demonstrate catastrophic cancellation when used like this:
$ ./foo.pl 1.e5 1.e-11
100000 1e-11
1.45519e-11 100000

(Note that the smaller number now has an error of around 50%)

Don't forget the following line in C:

a ^= b ^= a ^= b;

It may not be obvious but, assuming a and b are integers, this single line swaps the values in a and b. It takes advantage of the fact that, given x XOR y = z, you can determine any of x, y, or z, given the other two. Pretty nifty, if you ask me.

-----

Ok, I just now noticed the "xor swap" node has this exact idea already there. I swear I DID NOT see it there until after I posted this writeup, but if you don't believe me, I'll understand.
A warning to amateurs:

All of the techniques under this heading (with the (possible) exception of the Perl method) rely on A and B not occupying the same location in RAM). They will yield zero for both values if the two variables have the same address.

While this may at first seem irrelevant, one often uses such a swap on array elements, for example after finding the minimum value during a pass of a sorting algorithm. In such a situation, the programmer must check that the two items to swap do not have the same array index.

If such a possibilty exists, using a third (scratch) variable to perform a swap (rather than an index check at every pass) will often yield significantly faster code than performing the swap in-place. Additionally, implicit use of register variables by the compiler, and branch prediction penalties in a given CPU architecture will magnify this difference greatly.

Log in or register to write something here or to contact authors.