1. 原题分析
刷leetcode的时候,一直会遇到不用加法乘法去实现2个数的加法乘法运算,这类题目基本上就是利用位运算没跑了,现在总结一下,
题目:剑指offer65. 不用加减乘除法做加法
https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/
分析:
设a=7,b=5;即a=111,b=101,引入无进位和进位的概率
无进位和 | 进位 | ||
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
可以看出无进位和等于二者的异或运算结果,进位等于二者的与运算结果,考虑到进位是在高位,可以将其左移一位
这样a+b = a^b + (a&b)<<1 【这样看可能不太明显,大家可以用笔写一遍,用二进制计算2个数的加法】
因为上式中还包含了“+”,我们可以将其转换成循环或者递归的方式,终止状态是进位为0,即a&b<<1==0
#include<iostream>
#include<cmath>
#include<vector>
#include <algorithm>
#include <map>
#include <algorithm>
#include <unordered_map>
using namespace std;
class Solution {
public:
int add(int a, int b) {
while (b != 0)
{
int c = unsigned(a & b) << 1; //需要转换成无符号数,否则对大的负数会溢出,加上括号是<<运算优先级比&高
a = a ^ b;
b = c;
}
return a;
}
};
int main()
{
Solution obj;
cout<<obj.add(111, 899);
return 0;
}
2. 引申
2.1 引申至10进制
设a=103,b=97,则进位是010,无进位和190,区别于二进制,这里需要对进位乘10,即:
a+b = 190 + 1*(10^1),所以对于任意2个数,二者和都可以看做进位+无进位和。
2.2 引申至减法
设a=13,b=7,a=0x1101,b=0x0111,则无借位差是1010,借位是0100,区别于加法,这里需要对借位进行减法,即:
a+b = 0x1010 - 0x0100 = 10 - 4 = 6;