Definately think of all numbers in here in binary system.
What You would usually like to find out in such code is a "loop invariant". In this case, You would like to see that a + b is constant after every iteration. Thus if b becomes 0 and we leave the loop, a must be equal to the sum of original a and b. The next step is to make sure that the loop will eventually terminate. We'll come back to this later, first let's figure out the invariant part, which in this case is using the equality:
a + b = (a ^ b) + 2 * (a & b)
where in the loop new a will be equal to old a ^ b and new b will be 2 * (a & b), which is the same as (a & b) << 1. That's the essense of Your problem - figuring out this equality. It's exactly how You do the addition.
I'll present two solutions.
In both I'll use a simple fact that:
x + y = x ^ y
Whenever x and y have no common bits set.
The short way to see this formally is to note that:
a + b = a + b - 2(a & b) + 2(a & b)
= (a - (a & b)) + (b - (a & b)) + 2(a & b)
= (a - (a & b)) ^ (b - (a & b)) + 2(a & b)
= (a ^ (a & b)) ^ (b ^ (a & b)) + 2(a & b)
= a ^ b + 2(a & b)
The lengthy solution uses mathematical induction as follows (this might be considered an overkill by some, but in my option it's worth to know it):
First make sure it works with a and b both equal to zero (You might also try for one bit numbers which explain a lot of how this algorithm works). Never forget about this step when using mathematical induction.
Next, assume this works for n-1 bit numbers, we've got to show that it works for n bit ones too. Now write a = 2a' + a'' = 2a' ^ a'' and b = 2b' + b'' = 2b' ^ b'' where a'', b'' are in set {0, 1} (then 2a' and a'' have no common bits set!).
Then:
(a ^ b) + 2(a & b) = (2a' ^ a'' ^ 2b' ^ b'') + 2((2a'' ^ a') & (2b'' ^ b')) =
(2a' ^ 2b') ^ (a'' ^ b'') + 2((2a'' & 2b'') ^ (a'' & b'')) =
(2a' ^ 2b') + (a'' ^ b'') + 2((2a'' & 2b'') + (a'' & b'')) =
(2a' ^ 2b') + 2((2a'' & 2b'') + (a'' ^ b'') + (a'' & b'')) =
2a' + 2b' + a'' + b'' = a + b
Now the last thing to check is that this loop really terminates.
to see this use the fact that at each step both a and b are non-negative, and that this remains true after each iteration.
Therefore we've got that b <= a + b.
Next note that after n steps b has to be ending with n zeroes. Thus we cannot do more than log_2(a+b) steps since we'd get either b = 0 or b = k * 2*n >= 2*n > 2**log_2(a+b) = a+b contradicting assumption.
Here ** denotes exponentiation of course.
In Java this algorithm would also work on negative integers. This is because of how negative integers are stored in Java and in most programming languages
Here, the addition and subtraction of signed and unsigned numbers works identically on bits, therefore code that works for unsigned numbers will also work for signed.