zoukankan      html  css  js  c++  java
  • 二进制小技巧

    x&(x-1)

    现在令 x = 10101000,接下来我们算一下 x&(x-1)的结果。

    首先我们回忆一下二进制减法的规则

    0-0=1-1=0 
    1-0=1 
    0-1=1(向高位借位) 
    例如,(11000011)2-(00101101)2的算式如下: 
    11000011 被减数 
    00101101 减数 
    --1111 借位 (减号是对齐美观用的) 
    ------------------- 
    10010110 差数 
    

    回到刚才的运算,根据二进制减法的规则,我们得: 
    x-1 = 10100111, 

    x  = 10101000, x & (x-1) = 10100000

    我们可以看出,x的最右边的1变成了0,如果我们继续对得到的结果再次执行这样的运算时,发现结果又变为 10000000,由此我们得到结论:x&(x-1) 是将二进制数最右边的1变成0,如果没有1则生成的二进制位全为0。

    ??? 
    我们看下面程序会输出什么 
    ???

    #include<stdio.h>
    int function(int num)
    {
        int count = 0;
        while(num)
        {
            count++;
            num = num&(num-1);
        }
        return count;
    }
    int main()
    {
        printf("%d
    ",function(888));
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    答案是:6 
      9999的二进制为1101111000,上面的function函数,利用x&(x-1)这个技巧,得到参数num转化为二进制后含1的个数。共有6个1,所以最后的输出结果为6。

    我们可以用此式来检查一个无符号数是否是2的幂。

    x&(x+1)

    令 x = 10101 011,则 x+1 = 10101100,x&(x+1) = 10101 000, 
    我们看出 x&(x+1) 将一个二进制数最右边0后的1全置为0。可以用来检测一个无符号整数是否为2^n - 1的形式(包括0和所有位均为1的情况)。

    (~x)&(x+1)

    析出最右侧的0位, 
    例:10100111 -> 00001000

    x&(-x)

    析出最右侧的1位,如果都没有则生成位均为0的数。 
    -x  的算法是 对x取反,再加1。 
    对 x = 01011000,-x = 10101000,x&(-x) = 00001000,即01011000 -> 00001000

    1. 当x为0时,x&(-x) 即 0 & 0,结果为0;
    2. 当x不为0时,x和-x必有一个为正。设x为正。

      1. 当x为奇数时,最后一位为1,取反加1没有进位,故x和-x除最后一位外前面的位正好相反,按位与结果为0,最后一位都为1,故结果为1
      2. 当x为偶数,且为2的m次方(m>0)时,x的二进制表示中只有一位是1(从右往左的第m+1位),其右边有m位0,左边也都是0(个数由表示x的字节数决定),故x取反加1后,从右到左第有m个0,第m+1位及其左边全是1。这样,x& (-x) 得到的就是x
      3. 当x为偶数,却不为2的m次方的形式时,可以写作x= y * (2^k)。其中,y的最低位为1。实际上就是把x用一个奇数左移k位来表示。这时,x的二进制表示最右边有k个0,从右往左第k+1位为1。当对x取反时,最右边的k位0变成1,第k+1位变为0;再加1,最右边的k位就又变成了0,第k+1位因为进位的关系变成了1。左边的位因为没有进位,正好和x原来对应的位上的值相反。二者按位与,得到:第k+1位上为1,左边右边都为0。结果为2^k,即x中包含的2的最大次方的因子。比如x=32(100000)时,其中2的最大次方因子为2^5,结果为32;x=28(11100)时,2的最大次方因子为2^2,结果为4。
  • 相关阅读:
    洛谷P3384 【模板】树链剖分
    hdu3518 Boring counting(后缀数组)
    CSL 的密码(后缀数组)
    洛谷P3809 【模板】后缀排序
    洛谷P2387 [NOI2014]魔法森林(LCT)
    洛谷P3366 【模板】最小生成树(LCT)
    Stanford机器学习课程(Andrew Ng)
    操作系统存储器管理选择题精练
    实验12:Problem I: 成绩排序
    实验12:Problem H: 整型数组运算符重载
  • 原文地址:https://www.cnblogs.com/kcfzyhq/p/8475584.html
Copyright © 2011-2022 走看看