使用位运算实现加减乘除
加法#
在二进制下,有异或操作、与操作、进位操作。异或操作是指两个数对应位置相同取0,不同取1;与操作是同为1取1,否则取0;进位就是各位置上的1或0左移若干位。
根据这些操作特性,加法可以分解成这样的过程,先是两个数异或,相当于得到了两个数没有进位的相加结果,然后两个数相与,相当于只有两个位置都是1的情况下该位置才能为1,再进一位,就等效了加法的进位操作,然后将这个无进位的相加结果与进位的结果进行相加,就等于一个完成的加法过程了。需要注意的是,无进位的相加结果和进位的结果的加法过程又可以分解,于是得到了一个递归过程。
int a = 13;
int b = 42;
while(b != 0) {
int temp = a ^ b;
b = (a & b) << 1;
a = temp;
}
cout << a;
减法#
学习四则运算的时候我们就知道,减去一个数等于加上这个数的相反数,二进制中相反数可以这样表示-x = ~x + 1
,也就是取反加1。
int a = 13;
int b = 42;
int c = ~b;
b = 1;
while(b != 0) {
int tmp = c ^ b;
b = (c & b) << 1;
c = tmp;
}
while(c != 0) {
int tmp = a ^ c;
c = (a & c) << 1;
a = tmp;
}
cout << a;
乘法#
乘法运算就像是列一个二进制的乘法竖式一样。假设x
是乘数,y
是被乘数,那么如果x
的当前位是1,就把y
直接加到结果中,否则就下一轮操作。
int a = 13;
int b = 42;
int res = 0;
while(b != 0) {
if((b & 1) != 0) {
int tmp_a = a;
// 执行加法
while( tmp != 0) {
int tmp = tmp_a ^ res;
tmp_a = (res & tmp_a) << 1;
res = tmp;
}
}
a <<= 1;
b >>= 1;
}
cout << res;
除法#
除法就是乘法的逆运算。
int a = 42, b = 4;
int quotient = 0; //商
int remain = a; //余数
for(int i = 31; i > -1; i--) { //除数左移等于被除数右移,还能避免溢出
if((remain >> i) >= b) {
int temp = 1 << i; //1在商中的各位
int temp2;
while(temp != 0) { //求商
temp2 = quotient ^ temp;
temp = (quotient & temp) << 1;
quotient = temp2;
}
temp = ~(b << i); //b左移i位后的相反数
temp2 = 1;
int temp3;
while(temp2 != 0) {
temp3 = temp ^ temp2;
temp2 = (temp & temp2) << 1;
temp = temp3;
}
while(temp != 0) { //求余
temp2 = remain ^ temp;
temp = (remain & temp) << 1;
remain = temp2;
}
}
}
//没有考虑负数情况,若引入负数需要标记结果的正负
cout << "位运算结果: " << quotient << endl;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通