1. 6 Write a function that adds two numbers. You should not use + or any arithmetic operators.
一看就是需要用逻辑运算实现加法。
逻辑运算有一些很巧妙的运用,比如不需要借助第三个变量,就可以交换两个变量的值:
a=a^b;
b=b^a;
a=b^a;
异或运算有两个特性:
1、一个数异或本身恒等于0,如5^5恒等于0;
2、一个数异或0恒等于本身,如5^0恒等于5。
交换两个整数a和b,无非是a=b和b=a这两个操作,当然,你不能直接这么做。该怎么变呢?
算式一:a=b^(a^a)=a^(a^b);
算式二:b=a^(b^b)^(a^a)=a^(a^b)^(a^b);
注意上面算式二中的a还是原来的a,不要认为是改变后的a。
为什么右边的式子都留个a,没为什么,我就是想把b做为临时变量来用,此处要注意,既然做为临时变量用那么b就是最后才计算出来的数。接下来认真的分析下上面的两个算式。得出以下java语句:
把a^b做为临时变量值赋给b(临时变量),得
b=a^b;
计算出a:
a=a^b;注意这时的b可就是上面的式子已改变过的b了。
计算出b:
b=a^b;注意仔细观察上面的式二。
至此完成了两个整数的交换。
本题的答案
To investigate this problem, let’s start off by gaining a deeper understanding of how we add
numbers. We’ll work in Base 10 so that it’s easier to see. To add 759 + 674, I would usually add
digit*0 from each number, carry the one, add digit[1] from each number, carry the one, etc.
You could take the same approach in binary: add each digit, and carry the one as necessary.
Can we make this a little easier? Yes! Imagine I decided to split apart the “addition” and “carry”
steps. That is, I do the following:
1. Add 759 + 674, but “forget” to carry. I then get 323.
2. Add 759 + 674 but only do the carrying, rather than the addition of each digit. I then
get 1110.
3. Add the result of the first two operations (recursively, using the same process described
in step 1 and 2): 1110 + 674 = 1433.
Now, how would we do this in binary?
1. If I two binary numbers together but forget to carry, bit[i] will be 0 if bit[i] in a and b are
both 0 or both 1. This is an xor.
2. If I add two numbers together but only carry, I will have a 1 in bit[i] if bit[i-1] in a and b
are both 1’s. This is an and, shifted.
3. Now, recurse until there’s nothing to carry.
int add_no_arithm(int a, int b) {
if (b == 0) return a;
<span style="white-space:pre"> </span>int sum = a ^ b; // add without carrying
<span style="white-space:pre"> </span>int carry = (a & b) << 1; // carry, but don’t add
<span style="white-space:pre"> </span>return add_no_arithm(sum, carry); // recurse
}