爲了適應邊緣計算的需求決定投入學習Go語言的浪潮,用了10年的java突然要去接受一個風格完全不一樣的語言感覺真是太刺激了。
最近在看《Go語言聖經》的時候看到裏面的一個計算二進制中1的個數的程序popcount,覺得挺有意思就拿出來分享一下吧。
程序代碼總計也沒幾行,可以說很一目瞭然了:
程序分爲兩個部分
1, 初始化構造一個長度爲256的數組
2, 主程序PopCount通過8次右移操作分別求低8位的1數量然後相加
那這麼明顯的結構,這麼清晰的代碼有啥好解讀呢?
主要原因是在第一遍看的時候產生了兩個疑問,我覺得有必要記錄一下解決疑惑的過程。
初始化數組爲什麼是256
這個問題需要和PopCount主程序結合看。
因爲在主程序中使用的算法是將64位的無符號整數切割成8個8位,而8位的無符號整數取值範圍是0-255(2^8-1),爲了完整表示這256個數值的1的位數,所以使用了長度爲256的數組。
初始化算法的依據是什麼
其實初始化的算法就一句話 pc[i] = pc[i/2] + byte(i&1),一句話就得出了整數中二進制1的個數字典表也太神奇了吧。怎麼來理解這個算法呢?經驗?定理?當然可以選擇記住就行。
但是我們還是可以嘗試着大聲的念出這段代碼的含義,
對於(整數i的1的個數)等於(整數i/2中1的個數)加上(i在低1位的1的個數)。
是不是有點靈感了?直接上圖吧
從圖中可以看出每個整數i的1的個數由兩部分組成
1, i/2的1的個數,這部分就對應算法中的pc[i/2]
2, i/2的餘數,這部分對應算法中的byte[i&1]
到這裏這段代碼的疑惑就全部解開了,嗯就是這麼Go!