( a ^ b ^ c ) + ( ( ( a & b ) | ( b & c ) | ( a & c ) ) << 1 )
加法
...
还没学会如何迈开脚步又怎么能跑起来 ... 三个数字之前 ... 我们先要从两个数字相加开始 ...
首先你要知道计算机里面的数字都是以二进制存储的 ... 你看到的数字 ... 在计算机看来都是 0 和 1 ...
我们随便挑两个数字比如 123 和 321 ... 转化成二进制之后用用竖式把它们加在一起 ...
' "'
001111011 = 123
+ 101000001 = 321
-------------
110111100 = 444
相同位置对齐 ... 从个位数加起 ... 相加的结果满二进一 ... 这个不用我多说了吧 ..?
'
和 "
'
表示由原来的数字产生的进位 ... "
表示由 '
不过事实上 ... 进位这个事情本身也是二进制 ... 0 和 1 嘛 ... 所以不妨就用二进制来表示 ...
'
001111011 ( a
101000001 ( b
010000010 ( c
我们得到了三个数字 ... a 和 b 是原来的数字 ... c 是进位 ...
回想我们刚刚竖式计算的过程 ... 是不是每次都是先计算一位的值 ... 然后再看有没有进位要加 ..?
我们现在用程序模拟这个过程 ... 不考虑进位的时候先把 a 和 b 相加 ...
0 ^ 0 = 0
1 ^ 0 = 1
0 ^ 1 = 1
1 ^ 1 = 0
+
而是用 ^
^
就是位运算操作符里面的 按位异或
关于位运算这里就不再赘述了 ...
总之 ... a 和 b 不进位相加之后 ... 我们的式子变成了这样 ...
'
010000010 ( c
+ 100111010 ( d
-------------
110111100 = 444
d = a ^ b
但是同时又出现了新的问题 ... 怎么得到 c ..?
回想一下 ... c 是怎么来的 ..? 是由进位转化来的 ... 进位又是怎么来的 ..? 满二进一 ...
也就是当 a 和 b 的某一位同时为 1 的时候 ... c 的相应位置的左边一位为 1 ...
换言之 ... 当 a 和 b 的左起第 n + 1 位同时为 1 的时候则 c 的左起第 n 位为 1 ...
c = ( a & b ) << 1
&
是位运算操作符里面的 按位与
... <<
是位运算操作符里面的 左移
如果你认真看了我刚刚说的那个在另外问题里的回答的话 ... 应该不会对这两个操作符有疑问 ...
到现在为止 ... 我们又把 c 和 d 转化回了与 a 和 b 相关的式子 ...
a ^ b
... 进位的部分是 ( a & b ) << 1
所以我们可以得到结论 ... a + b = ( a ^ b ) + ( ( a & b ) << 1 )
...
绕了一大圈 ... 我们学会了怎么把两个数相加改为另外两个数相加 ...
这个看似没用的式子 ... 恰恰是解决这道题的关键 ...
如果你愿意 ... 可以一直这么写下去 ... 比如把这个式子继续拆分变成下面的样子 ...
(a ^ b) ^ ( ( a & b ) << 1 ) + ( ( a ^ b ) & ( ( a & b ) << 1 ) )
然后继续继续 ... 直到最右边那一项左移若干次之后变成 0 ... 你就实现了完全不用加号的加法 ...
在这个时候 ... 你加上一个新的数字 ... 就实现了一个加号的三个数字相加 ...
当然如果你仍然愿意继续的话 ... 甚至可以实现不用加号的三个数字相加 ...
唯一的问题就是最终的式子会长到一个屏幕都显示不下 ... 各种没法看 ...
所以我们现在回归最初 ... 继续列竖式 ... 看看三个数相加的时候到底发生了什么 ...
我们再随便挑三个数字 ... 比如 111 222 和 333 ...
""#""##''
0001101111 = 111
0011011110 = 222
+ 0101001101 = 333
--------------
1010011010 = 666
'
表示由原来的数字产生的进位 ... "
表示由 '
#
表示原来的数字在这里会产生进位但由于 '
或 "
'
和 #
0001101111 ( a
0011011110 ( b
0101001101 ( c 0010011110 ( d
我觉得都到现在了 ... 不用我说你应该也可以看出规律了吧 ...
只要 a b c 三个数字的某一位至少有两个为 1 ... 在 d 的相应位置的左边一位就为 1 ...
d = ( ( a & b ) | ( b & c ) | ( a & c ) ) << 1
|
是位运算操作符里面的 按位或