看到,挺感兴趣的,我就现写了,大家看到后也验证下对错吧。
第一题,无符号整数加法
参考链接
ps:\~第二个符号貌似很难打出来啊
逻辑运算,即二进制运算,无外乎与&、或|、非 \~、异或^以及移位>>,<<等操作;
而加法运算,在十进制中,只有按位相加以及进位两个操作。
从二进制角度也一样,就是bit位相加,加上相应的进位
1、bit位相加,通过逻辑运算的异或操作可以实现,如0+1=1,1+0=1,0+0=0;
2、进位运算,通过逻辑运算的与操作可以实现,如1+1=1,因为进位是往高位+1,因此需要将进位结果左移一位。
将上述两个操作再做加法运算,就是加法运算的结果,这是一个递归的过程,也可以通过非递归即循环来实现。
如求a+b,等价于(a^b)+(a&b)<<1
测试代码:
//Note:只是简单地验证了几个情况
#include<iostream>
using namespace std;
typedef unsigned int uint;
uint add(uint a,uint b){
//递归终止条件为b==0为真
if(!b)return a;
//否则根据公式继续递归
return add((a^b),(a&b)<<1);
}
int main(){
int a,b;
while(true){
cin>>a>>b;
cout<<add(a,b)<<endl;
}
return 0;
}
第二题,符号整数的乘法
(看到这道题让我想到了快速幂)
不善于表达,这里给个我的想象过程,想象过程基于以下两个情况:
1.乘法变成加法
2.乘法的两个操作数写成二进制
假设是812,
8的二进制是1000,12的二进制是1100
12个8相加
12的二进制 1 1 0 0
对应8的个数 8 4 2 1 (i位的个数为i-1位的个数的两倍,i>1)
应该加上的 64 32 0 0 (有1就加,没1就为0)
812 = 96 = 64+32
根据以上思想:.
//Note:只是简单地验证了几个情况
#include<iostream>
using namespace std;
typedef unsigned int uint;
uint mul(uint a,uint b){
//存储答案
uint ans = 0;
//b的位数未遍历完
while(b>0){
//b的最低为1
if(b&1)ans+=a;
//加数翻倍
a+=a;
//准备检测下一位
b>>=1;
}
return ans;
}
int main(){
int a,b;
while(true){
cin>>a>>b;
cout<<mul(a,b)<<endl;
}
return 0;
}
第三题,模指数运算
(快速幂)
这道题的思想跟第二题是一样的,请对比代码发现差异。
这里还是用无符号整数好了。
//Note:只是简单地验证了几个情况
#include<iostream>
using namespace std;
typedef unsigned int uint;
uint pow_mod(uint a,uint b,uint mod){
//存储答案
uint ans = 1;
//b的位数未遍历完
while(b>0){
//b的最低为1
if(b&1)ans=ans*a%mod;
//乘数翻倍
a=a*a%mod;
//准备检测下一位
b>>=1;
}
return ans;
}
int main(){
int a,b,mod;
while(true){
cin>>a>>b>>mod;
cout<<pow_mod(a,b,mod)<<endl;
}
return 0;
}
第四题,判断一个整数是否为2的次方
(搜索补码,原码,或者lowbit)
#include<iostream>
using namespace std;
int main(){
int a;
while(true){
cin>>a;
//注意一下a&-a的值,建议用程序以二进制值输出,与a进行对比
if((a-(a&-a))==0&&a!=0)cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}
最后一题,好多,我放弃了