Java Integer类具有静态方法highestOneBit方法,该方法将在指定值的最高一位的位置返回一个单个一位的值;如果指定值本身等于,则返回零零。
例如int 17的输入将返回16;由于17可以二进制表示为10001,所以它将返回最远的一位,等于16。
在Integer类中,它在Java文档中具有以下实现。
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);
}
我只想知道以这种方式实现它的逻辑以及使用移位操作的逻辑 。谁能给它一点点光。
答案 0 :(得分:4)
此算法为给定的i
计算其二进制表示形式:
0..01XXXXXXX...XXXX
值
0..011111111...1111
这就是5个|=
运算符的作用。
然后,在return语句中,它从中减去右移一位的值
0..001111111...1111
获得结果
0..010000000...0000
它如何工作:
第32位(最左侧)可能的最高1位。假设输入数字在该位中有1:
1XXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
您或该值右移1 (i >> 1)
并得到
11XXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
然后将您或该新值右移2 (i >> 2)
并得到
1111XXXX XXXXXXXX XXXXXXXX XXXXXXXX
然后将您或该新值右移4 (i >> 4)
并得到
11111111 XXXXXXXX XXXXXXXX XXXXXXXX
然后将您或该新值右移8 (i >> 8)
并得到
11111111 11111111 XXXXXXXX XXXXXXXX
最后,您或该新值的值向右移16 (i >> 16)
并得到
11111111 11111111 11111111 11111111
如果最高的1位小于第32位,则这些操作仍会将其右边的所有位都变为1,并使其余(较高的位)保持为0。
答案 1 :(得分:1)
i |=
语句有助于计算与i
相同长度的序列。例如,对于101011
,它计算111111
。我已经说明了它在this answer中的工作方式(由于我在移动设备上,因此目前无法重新输入)。
因此,基本上,一旦有了一串字符串,将其自身右移一位就可以得出H.O。位。
111111 - (111111 >>> 1) = 111111 - 011111 = 100000
答案 2 :(得分:1)
前五行(i |= (i >> x)
)会将最高1位以下的每一位都设置为1。然后,最后一行将减去最高1位以下的每1位,因此只有最高1位会保留下来。
为简单起见,我们假设int
为8位。在这种情况下,代码将如下所示:
public static int highestOneBit(int i) {
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
return i - (i >>> 1);
}
现在,假设我们的值为128(10000000
)。这将发生:
// i == 10000000
i |= (i >> 1); // i = 10000000 | 11000000 = 11000000
i |= (i >> 2); // i = 11000000 | 11110000 = 11110000
i |= (i >> 4); // i = 11110000 | 11111111 = 11111111
return i - (i >>> 1); // 11111111 - 01111111 = 10000000
>>
是算术右移,因此它将保留带符号的位。
最后的>>>
是逻辑右移,它将不保留带符号的位。它将始终在左侧插入零。
现在,让我们尝试64(01000000):
// i == 01000000
i |= (i >> 1); // i = 01000000 | 00100000 = 01100000
i |= (i >> 2); // i = 01100000 | 00011000 = 01111000
i |= (i >> 4); // i = 01111000 | 00000111 = 01111111
return i - (i >>> 1); // 01111111 - 00111111 = 01000000