为了适应边缘计算的需求决定投入学习Go语言的浪潮,用了10年的java突然要去接受一个风格完全不一样的语言感觉真是太刺激了。 

最近在看《Go语言圣经》的时候看到里面的一个计算二进制中1的个数的程序popcount,觉得挺有意思就拿出来分享一下吧。

 

程序代码总计也没几行,可以说很一目了然了:

image.png

程序分为两个部分

1, 初始化构造一个长度为256的数组

2, 主程序PopCount通过8次右移操作分别求低8位的1数量然后相加

 

那这么明显的结构,这么清晰的代码有啥好解读呢?

主要原因是在第一遍看的时候产生了两个疑问,我觉得有必要记录一下解决疑惑的过程。

 

初始化数组为什么是256

这个问题需要和PopCount主程序结合看。

因为在主程序中使用的算法是将64位的无符号整数切割成88位,而8位的无符号整数取值范围是0-2552^8-1),为了完整表示这256个数值的1的位数,所以使用了长度为256的数组。

初始化算法的依据是什么

其实初始化的算法就一句话 pc[i] = pc[i/2] + byte(i&1),一句话就得出了整数中二进制1的个数字典表也太神奇了吧。怎么来理解这个算法呢?经验?定理?当然可以选择记住就行。

 

但是我们还是可以尝试着大声的念出这段代码的含义,

对于(整数i1的个数)等于(整数i/21的个数)加上(i在低1位的1的个数)。

是不是有点灵感了?直接上图吧

image.png

从图中可以看出每个整数i1的个数由两部分组成

1, i/21的个数,这部分就对应算法中的pc[i/2]

2, i/2的余数,这部分对应算法中的byte[i&1]

 

到这里这段代码的疑惑就全部解开了,嗯就是这么Go