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不进位的和
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<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(逻辑代数基本知识).
~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<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 |