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位 = 该整数二进制形式的最高位。

 

 

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

posted @ 2019-12-27 09:55  不咬人的兔子  阅读(816)  评论(0编辑  收藏  举报