zoukankan      html  css  js  c++  java
  • 二进制x&(x-1);

    求下面函数的返回值(微软

    int func(x) 

        int countx = 0; 
        while(x) 
        { 
              countx ++; 
              x = x&(x-1); 
         } 
        return countx; 

    假定x = 9999。 答案:8

    思路:将x转化为2进制,看含有的1的个数。

     

    求下面函数的返回值(微软) -- 统计1的个数
    -------------------------------------
    int func(int x)
    {
        int countx = 0;
        while(x)
        {
            countx++;
            x = x&(x-1);
        }
        return countx;


    假定x = 9999
    10011100001111
    答案: 8

    思路: 将x转化为2进制,看含有的1的个数。
    注: 每执行一次x = x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1将会将该位(x用二进制表示时最右边的一个1)变为0。




    判断一个数(x)是否是2的n次方?
    -------------------------------------
    #include <stdio.h>

    int func(int x)
    {
        if( (x&(x-1)) == 0 )//只有二进制含有1个1的时候,x是2 的n次方!!!
            return 1;
        else
            return 0;
    }

    int main()
    {
        int x = 8;
        printf("%d ", func(x));
    }


    注: 
    (1) 如果一个数是2的n次方,那么这个数用二进制表示时其最高位为1,其余位为0。
    (2) == 优先级高于 &

     

     

    网友1:

    x=x&(x-1) 
    ============== 
    以前没有见过这样的表达式,分析一下发现发明这个表达式的人是个高手。 
    表达式的意思就是把x的二进制表示从最低位直到遇到第一个1的比特置0。 
    例如: 
    e1: 
    x          =   01001000 
    x-1       =   01000111 
    x&(x-1)=01000000 
    e2: 
    x           =   01001001 
    x-1       =   01001000 
    x&(x-1)=01001000
     
    我的总结:
    就用e1作为例子
    第一次位于运算的结果是01000000
    那么继续x-1,则x-1=00111111
    那么继续位于运算:
    01000000&00111111=00000000
    此时循环的变量x为0,循环终止。
    用来计数的countx也就是说明了二进制数种有几个1.
    但是我们传进去的参数是整数,例如传9999呢?
    看到&运算,肯定是变成二进制算,所以传什么就是多虑了。
     
     
     
    网友2:
    位运算。 
    &是位与。
    我觉得楼主应该知道&这个是位运算中的位与运算, 
    楼主只是想知道x=x&(x-1)到底有什么功能~~
    网友3:
    <Hacker 's   Delight> 这本书第1章就有介绍,这种算法是把一个二进制数最右边的一个1变成0。 

    一个简单的程序,先给出运算结果: 

    1011001 
    1011000 
    1010000 
    1000000 

    这是代码: 

    #include   <stdio.h> 


    void   OutBin(int   n) 

    int   a[32],   l   =   0; 

    if(n   ==   0)   { 
    printf( "0 "); 
    return; 


    while(n   >   0)   { 
    a[l++]   =   n   %   2; 
    n   > > =   1; 


    while(l--)   
    printf( "%d ",   a[l]); 


    int   main() 

    int   x   =   89; 

    OutBin(x); 
    printf( " "); 

    x   &=   x-1; 

    OutBin(x); 
    printf( " "); 

    x   &=   x-1; 

    OutBin(x); 
    printf( " "); 

    x   &=   x-1; 

    OutBin(x); 
    printf( " "); 

    return   0; 
    }
     
     
    网友4:
    那可以通过调试找出一点规律~~~ 
    当   x   =   0,结果为0 
    <0,0> , <1,0> , <2,0> , <3,2> , <4,0> , <5,4> , <6,4> , <7,6> , <8,0> , <9,8> , <10,8> , <11,10> , <12,8> , <13,12> , <14,12> , <15,14> , <16,0> , <17,16> , <18,16> , <19,18> , <20,16> , <21,16> , <22,20> , <23,22> , <24,16> , <25,24> , <26,24> , <27,26> , <28,24> , <29,28> , <30,28> , <31,30> , <32,0> ... 
    所以得出结论为: 
    当x为奇数的时候,x=x&(x-1)它的值相当于x   =   x-1;一样的效果~~~ 
    当x为2的N次幂时,结果为0; 
    其他希望下面人能找出一点规律出来~~~
     
     
    网友5:
    位运算里有学问呀, 
    例如众所周知的交换算法: 
    void   swap(int   i1,   int   i2) 

            i1   ^=   i2; 
            i2   ^=   i1; 
            i1   ^=   i2; 

    还有,我今天看了Minix操作系统作者写的《操作系统   设计与实现》(写的比William   Stalling的《操作系统   内核与设计原理》有条理而且清晰紧凑得多,后者内容芜杂)中的页面替换算法之一矩阵法,就是用位运算实现的: 
    假设内存分为n页,那么高速缓存一个n   x   n的比特矩阵,开始时全置0,如下(假设n=4): 
        0   1   2   3 
    0   0   0   0   0 
    1   0   0   0   0 
    2   0   0   0   0 
    3   0   0   0   0 
    每次内存访问时,如果访问的是i页,那么先把矩阵的第i行置1,然后把矩阵的第i列置0,这样i行的二进制的值越小就表示i页最长时间最近没有被访问。例如假设访问的次序为0-2-3-1,那么该矩阵的变化过程为: 
        0   1   2   3 
    0   0   1   1   1         0   1   0   1         0   1   1   0         0   0   1   0 
    1   0   0   0   0         0   0   0   0         0   0   0   0         1   0   1   1 
    2   0   0   0   0         1   1   0   1         1   1   0   0         1   0   0   0 
    3   0   0   0   0         0   0   0   0         1   1   1   0         1   0   1   0 
    第三个例子是Windows   GDI的二元和三元光栅操作的编码。比较复杂,就不讲了。
    更正: 
    void   swap(int   i1,   int   i2) 
    改成: 
    void   swap(int&   i1,   int&   i2)
  • 相关阅读:
    Python入门篇-解析式、生成器
    使用Kerberos进行Hadoop认证
    Python标准库-datatime和time
    使用Cloudera Manager部署HUE
    使用Cloudera Manager部署oozie
    使用Cloudera Manager部署Spark服务
    HDFS重启集群导致数据损坏,使用fsck命令修复过程
    关系型数据的收集
    使用Cloudera Manager搭建Kudu环境
    分布式结构化存储系统-Kudu简介
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/4369919.html
Copyright © 2011-2022 走看看