Sum of Two Integers

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需要错位相加,因此需要对每次逻辑与之后进行左移。
image
注意点:进位左移操作会丢失最高位,如果最高位为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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值