首页 > 代码库 > 求一个数后八位二进制1的个数

求一个数后八位二进制1的个数

//**********************************第一种方法
//将一个数右移来按位与,判断最后一位是不是1,进行八次
    int a = 15;
    int ccc = 0;
    for(int i = 0;i<8;i++)
    {
        int b =    a & 1;
        a = a>>1;
        if(1 == b)
        cout<<"有一个1\t";    
    }
//**********************************第二种方法
//将1左移来判断,和第一种方法相反
    int c = 15;
    for(int i = 0;i<8;i++)
    {
    int d = c &  (1<<i);
    if(d)
        cout<<"有一个1\t";
    }
//**********************************第三种方法
//和第二种方法相同,不过第二种是将1左移(变成2,4,8,16),而这里直接变成2的幂
    int e = 15;
    double t = 2;
    for(double i = 0;i<8;i++)
    {
        int tt = (pow(t,i));
        int f =    e & tt;
        if(f)
            cout<<"有一个1\t";
    }
//**********************************第四种方法
//和第一种方法类似,第一种方法是数的最后一位循环和1按位与判断,这里和2的30次方+2的29次方到2的0次方的和-1,相当于是0(30个1)0,取反,1(30个0)1,也是相当于最后一位和1按位与,不写成2的31次是因为int溢出
    int g = 15;
    int max = 0;
    double two = 2;
    for(int j = 0;j<31;j++)
    {
        max += pow(two,j) ;
    }
    for(int i = 0;i<8;i++)
    {
        int a=~(max-1);
        int h =    g & (a);
        if(1 == h)
            cout<<"有一个1\t";
            g>>=1;
    }
//**********************************第五种方法
//和第一种方法类似,对2取模得到是这个数的最后一位,然后和1按位与
    int r = 15;
    for(int i = 0;i<8;i++)
    {
        int l = ( r%2 ) & 1;
        if(1 == l)
            cout<<"有一个1\t";
        r>>=1;
    }
//***********************************第六种方法
//方法和第一种类似,除2相当于右移1位,然后和1按位与
    int z = 15;
    for(int i = 0;i<8;i++)
    {
        int x = z & 1;
        if(1 == x)
            cout<<"有一个1\t";
        z /= 2;
    }
//*************************************第七种方法
//取模来看最后一位,取模的结果只有0和1,用除来向右移位
    int cc = 15;
    for(int i = 0;i<8;i++)
    {
        int v =  cc % 2 ;
        if(1 == v)
            cout<<"有一个1\t";
        cc = cc / 2;
    }
//**********************************第八种方法

//这是最优的方法,叫平行算法,没有循环,假如看15里面有多少个1,15是1111 1111

//看奇数位有多少个1,与奇数位都是1的按位与能得出:15&0101 0101(85)得出0101 0101,看偶数位有多少个1:15&1010 1010(170)得出1010 1010,将左边的右移和右边的对齐来加
//偶数位是1010 1010右移1,01010101和奇数位相加1010 1010
//思想就是两位两位来看,看15的倒数第一位和倒数第二位有多少个1,分别有一个1,加起来是2,刚刚加起来的结果是1010 1010,倒数第二位1不就是2,说明是倒数第一位和倒数第二位一起看有2个1

//同样的这次看倒数第一位倒数第二位和倒数第三位和倒数第四位有多少个1:
//上次算的结果1010 1010,将倒数第一位和倒数第二位看做是1个数,看看里面有多少个1,按位与,和0011 0011,得出0010 0010
//将倒数第三位和倒数第四位看做一个数,看里面有多少个1,按位与,和1100 1100,得出1000 1000
//倒数第三位和倒数第四位在左边,将左边的和右边的对齐,将1000 1000右移2得0010 0010
//右移后的结果和倒数第一位和倒数第二位的结果相加 0010 0010 + 0010 0010 = 0100 0100

//同样的将倒数1-4位看做一个数,看看里面有多少个1,所以0100 0100 & 0000 1111 = 0000 0100
//看倒数5-8有多少个1,所以0100 0100 & 1111 0000 = 0100 0000
//将左边的右移4,倒数5-8位在左边,右移后位0000 0100
//相加 0000 0100 + 0000 0100 = 0000 1000(8,15里面有8个1)

//右移为什么是1、2、4、8、16,习惯2的倍数

//自己根据平行算法写的

    int oo = 15;
    int n = ( oo & 85 ) + ( ( oo & 170 )>>1 );
     n = ( n & 51 ) + ( ( n & 204 )>>2 );
     n = ( n & 15 ) + ( ( n & 240)>>4 );
        cout<<n;
//网上的代码,和平行算法
    int o = 15;
    int p1 = 0x55;
    int p2 = 0x33;
    int p3 = 0x0f;
    int p = ( o & p1 ) + ( ( o>>1 ) & p1 );
    p = ( p & p2 ) + ( ( p>>2 ) & p2 );
    p = ( p & p3 ) + ( ( p>>4 ) & p3 );
    cout<<p<<endl;

求一个数后八位二进制1的个数