#include <iostream>
#include <stdio.h>
using namespace std;
/*
问题:编写一个函数,将两个数字相加。不得使用+或其他算术运算符。
分析:既然不能使用+,应该就是位运算了。
可以将两个数字每次向右移动,每次将移动后的最低位进行与操作,若与操作结果为1,说明这两个数最后的都为1就进位,直到两个数都变成0
假设: 3 + 10
3对应: 00011
10对应: 01010
初始化一个结果result为0:每次将两个数最低位计算后的结果存放在result的第0位,第1位,..,
即可。
那么问题的关键变成:如何求两个数最低位,求某个数的第i位,可以采用将该数与(1<<i)进行与运算
设两个数分别为a,b
int pass = 0;
while( a && b)
{
int aBit = a & 1;
int bBit = b & 1;
//需要进位
if( ( 1 == aBit && 1 == bBit) || ( 1 == aBit))
{
pass = 1;
}
resultBit = ;
result |= resultBit;
}
书上解法:比如759 + 674,加法的:相加和进位拆分开:
1】759和674相加,不进位,得到323
2】759和674相加,只进位,得到1110
将1110 + 323 = 1433
上述只加不进位,就是异或操作
只进位不加,只要a和b的i-1位皆为1,总和的第i位为1,就是AND加上位移操作
输入:
3 5
3 -5
-3 -5
0 5
输出:
8
-2
-8
5
关键:
1
书上解法:比如759 + 674,加法的:相加和进位拆分开:
1】759和674相加,不进位,得到323
2】759和674相加,只进位,得到1110
将1110 + 323 = 1433
上述只加不进位,就是异或操作
只进位不加,只要a和b的i-1位皆为1,总和的第i位为1,就是AND加上位移操作
//递归得加法
int addRecursive(int a ,int b)
{
//注意递归的出口是: b为0,会导致sum为a , pass为0; 如果a为0,那么sum=0,pass为0
if(0 == a)
{
return b;
}
if(0 == b)
{
return a;
}
//累加,但不进位,通过异或实现
int sum = a ^ b;
//只进位,通过与操作,然后左移一位实现
int pass = (a & b) << 1;
return addRecursive(sum , pass);
}
2 注意,由于负数即使右移,填充的也是1,导致while(num1 && num2)陷入死循环,最好的办法就是采用(1<<i)次方取与 或者 次数超过32次就终止
int add(int num1 , int num2)
{
int pass = 0;
int result = 0;
pair<int, int> resultPair;
int resultBit;
int count = 0;
//注意,由于负数即使右移,填充的也是1,导致while(num1 && num2)陷入死循环,最好的办法就是采用(1<<i)次方取与 或者 次数超过32次就终止
//while(num1 || num2)
while(true)
{
//说明其中有一个是负数,直接退出循环
if(count >= 32)
{
break;
}
int bit1 = num1 & (1 );
int bit2 = num2 & (1 );
resultPair = getPassAndBit(bit1 , bit2 , pass );
resultBit = resultPair.first;
pass = resultPair.second;
result |= (resultBit << count);
num1 >>= 1;//右移一位
num2 >>= 1;
count++;
}
return result;
}
*/
//计算当前位和进位,pair第一个元素为当前位,第二个元素为进位
pair<int , int> getPassAndBit(int bit1 , int bit2 , int pass )
{
//如果全为0,进位为0,当前位为0
if( 0 == bit1 && 0 == bit2 && 0 == pass )
{
pair<int, int> result(0, 0);
return result;
}
//如果全为1,进位为1,当前位为1
else if( 1 == bit1 && 1 == bit2 && 1 == pass)
{
pair<int, int> result(1, 1);
return result;
}
//排除全1和全0的情况后:只剩两种可能:三者异或结果为0或1
else
{
//bit1,bit2,pass中有两个1,1个0,三者异或结果为0,此时当前位为0,进位为1
if( (bit1^bit2^pass) == 0)
{
pair<int, int> result(0, 1);
return result;
}
//bit1,bit2,pass中有两个0,1个1,三者异或结果为1,此时当前位为1,进位为0
else
{
pair<int, int> result(1, 0);
return result;
}
}
}
int add(int num1 , int num2)
{
int pass = 0;
int result = 0;
pair<int, int> resultPair;
int resultBit;
int count = 0;
//注意,由于负数即使右移,填充的也是1,导致while(num1 && num2)陷入死循环,最好的办法就是采用(1<<i)次方取与 或者 次数超过32次就终止
//while(num1 || num2)
while(true)
{
//说明其中有一个是负数,直接退出循环
if(count >= 32)
{
break;
}
int bit1 = num1 & (1 );
int bit2 = num2 & (1 );
resultPair = getPassAndBit(bit1 , bit2 , pass );
resultBit = resultPair.first;
pass = resultPair.second;
result |= (resultBit << count);
num1 >>= 1;//右移一位
num2 >>= 1;
count++;
}
return result;
}
//递归得加法
int addRecursive(int a ,int b)
{
//注意递归的出口是: b为0,会导致sum为a , pass为0; 如果a为0,那么sum=0,pass为0
if(0 == a)
{
return b;
}
if(0 == b)
{
return a;
}
//累加,但不进位,通过异或实现
int sum = a ^ b;
//只进位,通过与操作,然后左移一位实现
int pass = (a & b) << 1;
return addRecursive(sum , pass);
}
void process()
{
int num1;
int num2;
while(cin >> num1 >> num2)
{
//int result = add(num1 , num2);
int result = addRecursive(num1 , num2);
cout << result << endl;
}
}
int main(int argc , char* argv[])
{
process();
getchar();
return 0;
}
程序员面试金典——解题总结: 9.18高难度题 18.1编写一个函数,将两个数字相加。不得使用+或其他算术运算符。
这篇博客介绍了如何在编程中不用加号或其他算术运算符实现两个数字的相加,主要利用位运算来完成。博主详细解析了位运算的思路,通过异或操作实现不进位相加,通过与操作并左移一位实现进位,结合递归解决负数相加的问题,避免了死循环。并通过示例代码展示了实现过程。
摘要由CSDN通过智能技术生成