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

1.加法

#include
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不进位的和

x 0 1 0 1
y 0 1 1 0
x^y 0 0 1 1

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

x 0 1 0 1
y 0 1 1 0
x&y 0 1 0 0
(x&y)<<1 1 0 0 0

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

2.减法

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

#include
#include
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
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(逻辑代数基本知识).

~1 1 1 1 1 1 1 1 0
a * * * * * * * *
a|~1 1 1 1 1 1 1 1 *

可见,如果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次方)。具体过程可以看下面:

x y y最后一位 ans
00000110 00001010 0 0
00001100 00000101 1 0110 * 0010 (左移1位相当于乘2)
00011000 00000010 0 0110*0010
00110000 00000001 1 0110*0010 + 0010*1000
01100000 00000000 0 0110*0010 + 0010*1000
循环结束

4.除法

#include
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

你可能感兴趣的:(C++学习,c++)