参考文章
https://blog.csdn.net/qq_27575841/article/details/105461223
参考文章中给的比较关键的信息是:
1)算法名称叫移位法
2)算法思想是将value中的所有bit相加
背景
工作中遇到产商sdk的算法,第一次没看懂,看了参考文章(方法四移位法)感觉关键部分写的有点含糊,这边推导一下。
疑问
看完参考文章,我还是有如下疑问(实际上我只看懂了算法名和思想。。):
1)为什么是0x55…、0x33…,作用或含义是什么?移位的作用是什么?
2)每一次计算之后,n的含义是什么?
3)为什么需要多次处理,处理到哪里为止?
解析
1)为什么是0x55…、0x33…,作用或含义是什么?
这边先简单化:
- 如果是1位二进制,其数值本身即可代表所包含的置位个数如0x1则为1位,0x0则为0位。
- 如果是2位二进制,则我们可以将其看为两组1位二进制。则置位数量的计算方法为 (n & 0x1) + ((n >> 1) & 0x1);(注意这里n只有2bit)
- 如果是4位二进制,则我们可以将其看为两组2位二进制。
- 如果是8位二进制,则我们可以将其看为两组4位二进制。
- 以此类推。
首先分析0x5(4bit),二进制是0101。则 n = (n & 0x55555555) + ((n >> 1) & 0x55555555); 这个算式可以解读为在每个4bit的范围内,以2bit为一组,计算出该4bit内的每个2bit组的置位数,存储在各组所占用的2bit位置上。
其次分析0x3(4bit),二进制是0x11,则 n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 这个算式可以解读为位每个4bit的范围内,以4bit位一组,计算出该4bit内的第0组2bit和第一组2bit的和,存储在各组的所占用的4bit位置上。
以此类推。
2)每一次计算之后,n的含义是什么?
从上面可以看出,我们不应该把n作为一个整体数值去看,而应该将其上的不同bit位看做是多个1bit组、2bit组、4bit组等等内置位数量的临时存储。
3)为什么需要多次处理,处理到哪里为止?
从1中的推算中可以看出:
第0次计算(即n本身的数值),n的每1bit组,存储的是该1bit内置位的个数。
第1次计算,n的每2bit组存储的是原来该2bit内置位的个数。
第2次计算,n的每4bit组存储的是原来该4bit内置位的个数。
以此类推。
我们会发现,第i次计算,那么以 2i bit为一组的bit位上存储的就是原来这 2i bit位上置位的个数。因此只需要让 2i ==(n的bit数),即可得出i的个数。