题目
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
思路
二进制中,两个数相加有如下的规律
- 如果对应的位上都为1,那么该位上就要归零,并且往左侧进一位;
- 如果对应的位数不全都是1(1/0, 0/1, 0/0三种情况),那么该位在相加时,如果是1/0,或者0/1,就可置为1,如果是0/0,那就置为0。
所以有如下解法:
- 先将各bit位相加,不计进位,用异或实现
- 加上进位,用与运算,全为1与之后为1,而不全为1的位则全部变为了0,该位相加会发生进位,使得左边一位加1,因此(m&n)<<1边可得到进位后要加的1的位置
- 将前面两步的结果相加,相加的时候还有可能再产生进位,因此二者相加的过程可以再次重复循环步骤1和2,直到(m&n)<<1变为了0,这时候不会再产生进位,退出循环。
#include <iostream> using namespace std; class Solution { public: int add(int num1,int num2); }; int Solution::add(int num1,int num2) { int sum=0,carry=0; do { sum=num1^num2; carry=(num1&num2)<<1; num1=sum; num2=carry; }while(num2!=0); return num1; } int main() { Solution s; cout<<s.add(3,3)<<endl; return 0; }
拓展
不定义新的变量交换两变量的值。
1.基于加法
void swqp(int a,int b) { a=a+b; b=a-b; a=a-b; }
2.基于异或运算
void swap(int a,int b) { a=a^b; b=a^b; a=a^b; }
用这个办法交换2个指针的内容.那么你要先检查2个指针指向的地址是否相同.不然会导致内容被清0
3.不用加减乘除做减法
- 首先,如果减数为0,则被减数即为减法的结果,运算结束。
但如果减数不为0,我们可以先把被减数和减数上同为1的位从两个数上去除。至于如何分离出值同为1的位,则可以通过求位与操作来做到;而把这些1分别中被减数和减数中去除,则可以通过按位异或来的操作来实现。 - 经步骤1处理后,被减数和减数在对应的位上,将或者通为0,或者分别为0和1,却不会同为1。此时:
如果对应位被减数=1,而减数=0,则所得结果对应位也为1;
如果对应位被减数=0,而减数=1,则所得结果对应位还是1,但此时须向前一位借1;
即,通过被减数与减数作位异或的操作得到临时结果,和通过对减数左移一位得到需从临时结果中减去的借数。 - 于是,经过步骤2后,原来的减法变成了要求:临时结果 - 借数
很明显,只要以临时结果为被减数,借数为减数,重复步骤1~3即可。
#include <iostream> using namespace std; class Solution { public: int add(int num1,int num2); int sub(int num1,int num2);//方法1 int sub1(int num1,int num2);//方法2 }; int Solution::add(int num1,int num2) { int sum=0,carry=0; do { sum=num1^num2; carry=(num1&num2)<<1; num1=sum; num2=carry; }while(num2!=0); return num1; } int Solution::sub(int num1,int num2) { //反码:解决负数加法运算问题,将减法运算转换为加法运算,从而简化运算规则 //补码:解决负数加法运算正负零问题,弥补了反码的不足 //减去一个数等于加上这个数的补码,把减法转化为加法运算 //求补码:原码每位取反末尾+1 return add(num1,add(~num2,1)); } int Solution::sub1(int num1,int num2) { while(num2!=0) { int temp=num1&num2;//1-1得0,计算每个标记两个数都为1的位 num1^=temp;//清除被减数为1的位 num2^=temp;//清除减数为1的位 num1|=num2; num2<<=1; } return num1; } int main() { Solution s; cout<<s.sub(3,2)<<endl; cout<<s.sub1(3,2)<<endl; return 0; }
code
class Solution { public: int Add(int num1, int num2) { _asm { MOV EAX,num1 MOV ECX,num2 ADD EAX,ECX } } };