Sum of Two Integers
作者:money
问题:
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
Example:
Given a = 1 and b = 2, return 3.
问题分析:
不适用加减符号实现两个整数的加和。这个只能通过位运算实现,有点类似cpu的加法实现。
异或操作(exclusive OR):
计算方式:
1+1=0
0+0=0
1+0=1
简单理解就是不进位加法
直接仅使用异或无法实现完整的加法,需要通过按位and求得每次计算的进位,并与异或结果相加。迭代相加后,直到没有进位,即是结果。
在C++中,异或操作通过”^”,与逻辑通过“&”或操作”|”,非操作 “~”。
例子:
设计了一个加法场景:29+143=172
将a作为异或的结果,b作为进位的结果,当迭代至进位为0,即b=0,此时的a就是最终的和。
因为进位部分b和异或的不进位和a需要错位相加,因此需要对每次逻辑与之后进行左移。
注意点:进位左移操作会丢失最高位,如果最高位为1,则说明sum值已经超过数据类型可定义的数据范围,此特殊情况意味着加法溢出
问题代码:
#include <iostream>
#include <string>
// submit these code to leetcode
// begin
class Solution {
public:
int getSum(int a,int b) {
int carry=0;
while(b!=0)
{
carry=a&b;
a=a^b;
b=carry<<1;
}
return a;
}
};
// end
// submit these code to leetcode
int main(){
Solution sum;
int a=0,b=0;
std::cout<<"input tow int"<<std::endl;
std::cin>>a>>b;
std::cout<<sum.getSum(a,b)<<std::endl;
return 0;
}
杂录:
异或的性质和作用:
简单理解就是不进位加法,如1+1=0,0+0=0,1+0=1。
性质:
1、交换律
2、结合律(即(a ^ b) ^ c == a ^ (b ^ c)
3、对于任何数x,都有x ^ x=0,x ^ 0=x
4、自反性 A XOR B XOR B = A xor 0 = A
作用:
一、交换两个整数的值而不必用第三个参数
A=A XOR B (a XOR b)
B=B XOR A (b XOR a XOR b = a)
A=A XOR B (a XOR b XOR a = b)
例子:
a = 9; b = 11;
a=a ^ b; 1001^1011=0010
b=b ^ a; 1011^0010=1001
a=a ^ b; 0010^1001=1011
a = 11; b = 9;
二、奇偶判断
^ a 操作就是将a中的每一位按位逐一进行异或,例如a=4’b1010,则b=1 ^ 0 ^ 1 ^ 0=0,由此可以判断a中为1的位数是奇数还是偶数,是一个便捷的操作。
三、运用距离:
1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现
一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空
间,能否设计一个算法实现?
解法一、显然已经有人提出了一个比较精彩的解法,将所有数加起来,减去1+2+…+1000的和。
这个算法已经足够完美了,相信出题者的标准答案也就是这个算法,唯一的问题是,如果数列过大,则可能会导致溢出。
解法二、异或就没有这个问题,并且性能更好。
将所有的数全部异或,得到的结果与1 ^ 2 ^ 3 ^ … ^ 1000的结果进行异或,得到的结果就是重复数。
但是这个算法虽然很简单,但证明起来并不是一件容易的事情。这与异或运算的几个特性有关系。
首先是异或运算满足交换律、结合律。
所以,1 ^ 2 ^ … ^ n ^ … ^ n ^ … ^ 1000,无论这两个n出现在什么位置,都可以转换成为1 ^ 2 ^… ^ 1000 ^ (n ^ n)的形式。
其次,对于任何数x,都有x ^ x=0,x ^ 0=x。所以1 ^ 2 ^… ^ n ^… ^ n ^… ^ 1000 = 1 ^ 2 ^…^ 1000 ^ (n ^ n)= 1 ^ 2 ^ …^ 1000 ^ 0 = 1 ^ 2 ^…^ 1000(即序列中除了n的所有数的异或)。
令,1 ^ 2 ^… ^ 1000(序列中不包含n)的结果为T,则1 ^ 2 ^… ^ 1000(序列中包含n)的结果就是T ^ n。T ^ (T ^ n)=n。所以,将所有的数全部异或,得到的结果与1 ^ 2 ^ 3 ^… ^ 1000的结果进行异或,得到的结果就是重复数。
1+2+…+1000的结果有高斯定律可以快速计算,但实际上1 ^ 2 ^ … ^ 1000的结果也是有规律的,算法比高斯定律还该简单的多。
google面试题的变形:一个数组存放若干整数,一个数出现奇数次,其余数均出现偶数次,找出这个出现奇数次的数?
参考:
异或的几个作用:http://www.cnblogs.com/danh/archive/2010/12/24/1915810.html
异或的性质及运用:http://www.cnblogs.com/suoloveyou/archive/2012/04/25/2470292.html