Bootstrap

原码、反码、补码以及lowbit运算

原码、反码、补码以及lowbit运算

原码:

可以用来计算正数加减,正数的原码、反码、补码都一样。
第一位为符号位,符号位0为正数,1为负数(32位字符,这里用4位来举例子,后面皆是用4位来举例子,其中第一位是符号位)。

1 1 1 1-71 1 1 0-61 1 0 1-51 1 0 0-41 0 1 1-31 0 1 0-21 0 0 1-11 0 0 0-00 0 0 000 0 0 110 0 1 020 0 1 130 1 0 040 1 0 150 1 1 060 1 1 17

反码:

反码的来源:

由于原码中正数(1)与负数(-1)计算错误,引入反码(ones complement),负数的反码=原码按位取反。

1 0 0 0-71 0 0 1-61 0 1 0-51 0 1 1-41 1 0 0-31 1 0 1-21 1 1 0-11 1 1 1-00 0 0 000 0 0 110 0 1 020 0 1 130 1 0 040 1 0 150 1 1 060 1 1 17

补码:

补码的来源:

由于原码中正数(5)与负数(-3)计算错误,答案都有正确答案差一,引入补码(two‘s complement),负数的二进制表示=补码=反码➕1,
计算机里都是通过补码来存储信息的。

1 0 0 0-81 0 0 1-71 0 1 0-61 0 1 1-51 1 0 0-41 1 0 1-31 1 1 0-21 1 1 1-10 0 0 000 0 0 110 0 1 020 0 1 130 1 0 040 1 0 150 1 1 060 1 1 17

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;
}
;