C++:用位运算实现加减乘除

1.加法

#include<iostream>
using namespace std;
int main()
{
	int x,y,ans,a,b;
	cin>>x>>y;					//输入两个加数
	a=x;
	b=y;
	while(y)
	{
		ans=x^y;				//求x,y的和(不进位)
		y=(x&y)<<1;				//求x,y的进位的数,令赋值给y
		x=ans;					//令不进位的值赋值给x,开始下一次求和
	}
	cout<<a<<"+"<<b<<"="<<ans;	//输出结果
}

两个数x、y求异或,得到的x,y不进位的和

x0101
y0110
x^y0011

x与y求与,再左移一位,得到的是进位的数。

x0101
y0110
x&y0100
(x&y)<<11000

将不进位的和与进位的数再求和,当进位为0的时候,循环结束,得到的就是运算的结果。

2.减法

与加法类似,就是将减数取反。

#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
	int x,y,ans,a,b;
	cin>>x>>y;					//输入两个减数
	a=x;
	b=y;
	y=-y;						//令y取负,转化为相加
	while(y)
	{
		ans=x^y;				//求x,y的和(不进位)
		y=(x&y)<<1;				//求x,y的进位的数,令赋值给y
		x=ans;					//令不进位的值赋值给x,开始下一次求和
	}
	cout<<a<<"-"<<b<<"="<<ans;	//输出结果
}

3.乘法

#include<iostream>
using namespace std;
int Add(int x,int y);
int main()
{
	int x,y,ans=0;
	cin>>x>>y;
	while(y)
	{
		if(~(~y|~1))		//判断y的二进制最后一位是否为1(为1则为True)
			ans=Add(ans,x);
		x=x<<1;
		y=y>>1;
	}
	
	cout<<ans;
}
int Add(int x,int y)	//加法运算函数
{
	int ans;
	while(y)
	{
		ans=x^y;				
		y=(x&y)<<1;				
		x=ans;					
	}
	return ans;
}

首先我们来看一下二进制的乘法可以这么分解,简单起见,我们让两个四位的二进制数相乘:
0110 * 1010 = 0110 * 1000 + 0110 * 0010
我们对于乘数(后一个数)进行了分解,为什么这样做呢,转化为十进制我们再看看就明白了:
6 * 10 = 6 * 8 + 6 * 2
也就是让被乘数乘以2的倍数,在二进制里面,一个数乘以2的倍数,就相当于左移对应的位数,这样,我们就可以运用位运算来实现乘法。所以
0110 * 1010 = 0110 * 1000 + 0110 * 0010
就相当于令0110左移3位再加上0110左移一位。

我们看主函数中if判断条件,1的二进制取反,得到的是一个最低为为0,其他位为1的数。这个数与一个数求或,相当于将一个数除最后一位全部置1(逻辑代数基本知识).

~111111110
a********
a|~11111111*

可见,如果x最后一位为0,则求或的结果再求反就是1,if里的语句执行。因为我们这里的a相当于程序里面的~y,所以当y的最后一位为1,则程序执行。也就是说当y最后一位为1,对x求和得到ans。这样做的原因就是我们之前举例说明的:
0110 * 1010 = 0110 * 1000 + 0110 * 0010
对于乘数要右移1位,被乘数要左移1位,当乘数右移m位时最小位为1,则此时左移了m位的被乘数相当于已经乘以了2^m(2的m次方)。具体过程可以看下面:

xyy最后一位ans
000001100000101000
000011000000010110110 * 0010 (左移1位相当于乘2)
000110000000001000110*0010
001100000000000110110*0010 + 0010*1000
011000000000000000110*0010 + 0010*1000
循环结束

4.除法

#include<iostream>
using namespace std;
int Add(int x,int y);
int Minus(int x,int y);
int main()
{
	int x,y,ans=0;
	cin>>x>>y;
	while(x>=y)
	{
		x=Minus(x,y);	//x-y赋值给x
		ans=Add(ans,1);	//ans++
	}
	cout<<ans;
}
int Add(int x,int y)	//加法运算函数
{
	int ans;
	while(y)
	{
		ans=x^y;				
		y=(x&y)<<1;				
		x=ans;					
	}
	return ans;
}
int Minus(int x,int y)	//减法运算函数
{
	int ans;
	ans = Add(x,-y);
	return ans;
}

除法的比较简单,就是用被除数不停减去除数,直到被除数小于除数。期间每减一次就令结果ans+1.稍作修改也可以写为求余 (x%y)的程序,大家可以自己试试。

5.小节

这部分程序就本身而言应用价值并不大,但是其中学到的利用位运算来处理数据特别重要。

操作符按位与按位或按位异或按位取反左移右移
操作符号&|^~<<>>
作用清零特定位特定位置1特定位值取反补码相当于乘2相当于除以2
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值