算法——整数规格化
1. 介绍
整数规格化的算法是我在阅读 Netty 源码时了解到的,它指的是 将一个整数经过规格化处理,变成大于或等于原数的最小的 2
的幂次方数。
2. 代码
public static int normalize(int n) {
n--;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
n++;
return n;
}
3. 逐步解释
n--
:对n
进行减1
操作,确保当n
本身就是2
的幂次方时,经过后续操作后结果依然是n
。n |= n >>> 1
:将n
右移1
位,然后与原数按位或,从而 把最高位1
右边的第1
位也置为1
。n |= n >>> 2
:将n
右移2
位,然后与原数按位或,从而 把最高位1
右边的第2, 3
位也置为1
。n |= n >>> 4
:将n
右移4
位,然后与原数按位或,从而 把最高位1
右边的第4, 5, 6, 7
位也置为1
。n |= n >>> 8
:将n
右移8
位,然后与原数按位或,从而 把最高位1
右边的第8, 9, ..., 15
位也置为1
。n |= n >>> 16
:将n
右移4
位,然后与原数按位或,从而 把最高位1
右边的第16, 17, ..., 31
位也置为1
。n++
:经过前面的操作,n
二进制表示中最高位1
及其右边的所有位都为1
。此时加1
操作会 让n
变成大于或等于原始n
的最小的 2 的幂次方数。
4. 演示
4.1 情况一:n 不是 2 的幂次方
对于二进制数 0b0100_1000
(只演示 8
位,更高位数以此类推),它的规格化流程如下:
原数: 0100 1000
n-- 后: 0100 0111
n |= n >>> 1后: 0110 0111
n |= n >>> 2后: 0111 1111
n |= n >>> 4后: 0111 1111
n |= n >>> 8后: 0111 1111
n |= n >>> 16后: 0111 1111
n++ 后: 1000 0000
4.2 情况二:n 是 2 的幂次方
对于二进制数 0b0100_0000
,它的规格化流程如下:
原数: 0100 0000
n-- 后: 0011 1111
n |= n >>> 1后: 0011 1111
n |= n >>> 2后: 0011 1111
n |= n >>> 4后: 0011 1111
n |= n >>> 8后: 0011 1111
n |= n >>> 16后: 0011 1111
n++ 后: 0100 0000
5. 总结
整数规格化可以使用本文讲解的算法,它的时间复杂度和空间复杂度都是 O ( 1 ) O(1) O(1),而且所有操作都是位运算,性能很高。它可能会应用于内存偏移量计算的场景。