比特计数
一个无符号32位整数 u
可以写成这样:
u = a31 * 231 + a30 * 230 + ... + a0 * 20
我们想知道 a31 + a30 + ... + a0
的值。
让我们比较 u >> k
的值:
u >> 0 = a31 * 231 + a30 * 230 + ... + a1 * 21 + a0 * 20
u >> 1 = a31 * 230 + a30 * 229 + ... + a1 * 20
u >> 2 = a31 * 229 + a30 * 228 + ...
...
u >> 29 = a31 * 22 + a29 * 21 + ...
u >> 30 = a31 * 21 + a30 * 20
u >> 31 = a31 * 20
我们将使用以下公式计算比特数:
u >> 0 - u >> 1 - u >> 2 - ... - u >> 31 = p
让我们看看为什么这个有效:
u >> 0 - u >> 1 - u >> 2 - ... - u >> 31
= u >> 0 - (u >> 1 + u >> 2 + ... + u >> 31)
= u - q
q
的值是多少?让我们逐位计算,查看上面
u>>k
的值。对于
a31
,它为:
a31 * 230 + a31 * 229 + ...
= a31 * (230 + 229 + ...)
= a31 * (231 - 1)
或者对于a30
:
a30 * 229 + a30 * 228 + ...
= a30 * (229 + 228 + ...)
= a30 * (230 - 1)
我们发现:q = a31 * (231 - 1) + a30 * (230 - 1) + ...
因此,
u - q = a31 * 231 - a31 * (231 - 1) + ...
= a31 + a30 + ... + a0
以3位块为单位计算位数
这个算法从做同样的事情开始,但是以3位块为单位:
u >> 0 = AaBbbCccDddEeeFffGggHhhIiiJjjKkk (each letter is a bit)
u >> 1 & 033333333333 = A Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk (blank = zero)
u >> 2 & 011111111111 = B C D E F G H I J K
通过上述算法取它们的差异,
uCount
中的每个八位组都包含在
u
中对应八位组中设置的位数。
uCount = αβγδεζηθικλ (each greek letter is an octet)
uCount >> 3 = αβγδεζηθικ
所以uCount + (uCount >> 3)
就是(λ+κ) * 20 + (κ+ι) * 23 + (ι+θ) * 26 + ...
通过与0o30707070707
的AND运算,我们掩盖了每个其他八进制数位,这样我们只计算每一对仅一次:
r = (λ+κ) * 640 + (ι+θ) * 641 + (η+ζ) * 642 + ...
= (λ+κ) * 20 + (ι+θ) * 26 + (η+ζ) * 212 + ...
这是一个64进制数,我们想要将其各位数字相加,得到α+β+γ+δ+ε+ζ+η+θ+ι+κ+λ
,我们的最终结果。为此,我们计算它的64进制数字根: 知道结果永远不会大于32,我们只需将数字模63。