原码、反码、补码以及lowbit运算
原码:
可以用来计算正数加减,正数的原码、反码、补码都一样。
第一位为符号位,符号位0为正数,1为负数(32位字符,这里用4位来举例子,后面皆是用4位来举例子,其中第一位是符号位)。
1 1 1 1(-7)
1 1 1 0(-6)
1 1 0 1(-5)
1 1 0 0(-4)
1 0 1 1(-3)
1 0 1 0(-2)
1 0 0 1(-1)
1 0 0 0(-0)
0 0 0 0(0)
0 0 0 1(1)
0 0 1 0(2)
0 0 1 1(3)
0 1 0 0(4)
0 1 0 1(5)
0 1 1 0(6)
0 1 1 1(7)
反码:
反码的来源:
由于原码中正数(1)与负数(-1)计算错误,引入反码(ones complement),负数的反码=原码按位取反。
1 0 0 0(-7)
1 0 0 1(-6)
1 0 1 0(-5)
1 0 1 1(-4)
1 1 0 0(-3)
1 1 0 1(-2)
1 1 1 0(-1)
1 1 1 1(-0)
0 0 0 0(0)
0 0 0 1(1)
0 0 1 0(2)
0 0 1 1(3)
0 1 0 0(4)
0 1 0 1(5)
0 1 1 0(6)
0 1 1 1(7)
补码:
补码的来源:
由于原码中正数(5)与负数(-3)计算错误,答案都有正确答案差一,引入补码(two‘s complement),负数的二进制表示=补码=反码➕1,
计算机里都是通过补码来存储信息的。
1 0 0 0(-8)
1 0 0 1(-7)
1 0 1 0(-6)
1 0 1 1(-5)
1 1 0 0(-4)
1 1 0 1(-3)
1 1 1 0(-2)
1 1 1 1(-1)
0 0 0 0(0)
0 0 0 1(1)
0 0 1 0(2)
0 0 1 1(3)
0 1 0 0(4)
0 1 0 1(5)
0 1 1 0(6)
0 1 1 1(7)
lowbit运算:
int lowbit(int x){
return x&(-x);
}
lowbit运算的返回值:
lowbit运算返回x二进制中最低位的1和后面的0所组成的十进制数。
lowbit运算处理的问题:
如何求一个数二进制表示含1的个数?
1、没有使用lowbit优化,会一直向前移动。
#include<iostream>
using namespace std;
int main(){
int n,cnt;
cin>>n;
while(n){
if(n&1==1){
cnt++;
}
n=n>>1;
}
cout<<cnt;
return 0;
}
2、使用lowbit优化,每次减去上一个数的lowbit会抹去上个的最后一位一会加快运行速度,不会一直向前移动就可以统计出一个数二进制中含一的个数。
#include<iostream>
using namespace std;
int lowbit(int x){
return x & -x;
}
int n;
int main(){
cin>>n;
while(n){
int x;
cin>>x;
int res=0;
while(x){
x-=lowbit(x);
res++;
}
n--;
cout<<res;
}
return 0;
}