zoukankan      html  css  js  c++  java
  • java

    看Integer源码的时候发现的= =感觉非常有意思。。。

        public static int highestOneBit(int i) {
            // HD, Figure 3-1
            i |= (i >>  1);
            i |= (i >>  2);
            i |= (i >>  4);
            i |= (i >>  8);
            i |= (i >> 16);
            return i - (i >>> 1);
        }

    核心算法就就是这个

    i |= (i >> 1);

    | 或运算 两个数字或运算只要其中一个的对应位是1那么结果为1

    比如   1010 | 1001 = 1011

    >> 右移 把数字的二进制向右位移,保留符号位(int最左位表示正负, 这里先不考虑负数情况)

    比如

    1010 >> 1    =    0101

    1010 >> 2    =    0010

    1010 换算为十进制为 10

    0101 换算为十进制为 5

    0010 换算为十进制为 2

    不难看出= =右移的本质其实是除以2,多少位就是除以2的多少次幂。

    首先int类型位数最大为16位,所以这里最大只右移了16位。

    先按方法手动算一下

    比如 0000 0000 1000 1110

    i |= (i >> 1);

    i >>1 = 0100 0111

    1000 1110   |   0100 0111   =  1100 1111

    i |= (i >> 2);  (此时i已经变成了 1100 1111)

    i >>2 = 0011 0011

    0011 0011  |  1100 1111 = 1111 1111

    ...

    因为或算法只要有1个是1那么这位就是1,所以很容易得出

    最后经过

    i |= (i >> 1);

    i |= (i >> 2);

    i |= (i >> 4);

    i |= (i >> 8);

    i |= (i >> 16);

    后   ( i 的最高位之后的所有位都会变成1)

    i = 1111 1111;   

    然后执行最后一步

    return i - (i >>> 1);

    >>>也是右移,只不过不保留符号位,这样可以保证最后结果不受负数影响,这里先不考虑负数情况。

    此时

    i = 1111 1111;   

    i >>> 1  = 0111 1111

    1111 1111 - 0111 1111 = 1000 0000 得到最高位。

    所以这个算法的本质:

    先把最高位右边的所有位都变成1

    然后此时: 数字 - 数字右移1位 = 该整数二进制形式的最高位。

    脑洞:可以不断左移一个数字直到这个数变成负数= = 然后也可以得到最高位是哪一位,虽说有点蠢= =

  • 相关阅读:
    centos安装vsftp
    php利用soap实现webservice 和利用soap调用其他语言的webservice
    php连接redis数据库 操作redis任务队列
    shopnc编译安装IM服务器node.js
    centos6.5 64位 yum install nginx的默认安装路径
    安装nfs服务器
    php扩展redis,编译安装redis服务
    x86_64编译JPEG遇到Invalid configuration `x86_64-unknown-linux-gnu'
    shopnc nginx优化配置文件
    nginx支持flv MP4 扩展nginx_mod_h264_streaming,nginx-rtmp-module-master,yamdi
  • 原文地址:https://www.cnblogs.com/clamp7724/p/12105776.html
Copyright © 2011-2022 走看看