計算二進位制位 1 的個數

2021-05-22 09:05:18 字數 2366 閱讀 3482

寫乙個函式,返回數字中二進位制位為'1'的個數。

比如36,化為二進位制得到100100,其中有2個'1'。

方法1:分別判斷各個位

bit_count(unsigned 

intn)

方法2:迴圈中直接計算1的數量

如何隻數'1'的個數?如果乙個數字至少包含乙個'1'位,那麼這個數字減1將從最低位開始依次向高位借位,直到遇到第乙個不為'0'的位。依次借位使得經過的位由原來的'0'變為'1',而第乙個遇到的那個'1'位則被借位變為'0'。

36 d = 100100 b

36-1 d = 100011 b

如果最低位本來就是'1',那麼沒有發生借位。

現在把這2個數字做按位與:n & n-1的結果是什麼?

2個數字在原先最低為'1'的位以下(包括這個位)的部分都不同,所以結果是保留了其他的'1'位。

36 & 36-1 d = 100000 

b這個結果剛好去掉了最低的乙個'1'位

bit_count(unsigned 

intn)

由於直接跳過'0'位,這個方法比上面的要略微快一些。

本來以為這個應該最快了,不過農夫三拳又給我看了乙個:

方法3:平行計算的- -這個太厲害了

pow(c) (1<

mask(c) (((unsigned long)-1) / (pow(pow(c)) + 1))

round(n, c) (((n) & mask(c)) + ((n) >> pow(c) & mask(c)))

bit_count(unsigned 

intn)

一下子看不明白,先把巨集展開來:

pow是計算2的冪

mask很奇怪,乙個全1的無符號數字除以2的冪的冪加1?

好在列印出來還能看得懂:

mask(0) = 55555555 h = 01010101010101010101010101010101

bmask(1) = 33333333 h = 00110011001100110011001100110011

bmask(2) = 0f0f0f0f h = 00001111000011110000111100001111

bmask(3) = 00ff00ff h = 00000000111111110000000011111111

bmask(4) = 0000ffff h = 00000000000000001111111111111111 b

這些mask分別把32位數字劃分為幾個部分。每個部分的前一半和後一半分別是全'0'和全'1'。

mask(0)分為16個部分,mask(1)分為8個部分,...

round中對n的處理:(n & mask) + (n >> pow & mask)

pow的值剛好是mask中連續'0'(或者連續'1')的長度。也就是說round把由mask分開的n的各個部分中的高pow位和低pow位相加。

為了便於說明,取 乙個簡單的部分:mask(1)的0011

假 設n的值為1001,那麼round後的結果就是10 + 01 = 11 b,把這個結果賦值給n,這時n的含義由原來的二進位制位串變為'1'位的數量。特別的,當round(n, 0)時,把n當作乙個32個部分各自'1'位的數量。('0'表示沒有'1',而'1'則表示有1個'1')

計算完n = round(n, 0)後,n是乙個16個部分各自'1'位數量的'陣列',這個'陣列'的每個元素只有2個二進位制位。最大值為2,足夠由2個二進位制位來表示。

接下來,計算完n=round(n,1)後,n是乙個8個部分各自'1'位數量的'陣列',這個'陣列'的每個元素只有4個二進位制位。最大值為4,足夠由4個二進位制位來表示。(實際只需要3個二進位制位)

...最後一步,計算n=round(n,4)後,n是乙個1個部分各自'1'位數量的'陣列',這個'陣列'的每個元素有32個二進位制位。最大值為32,足夠由32個二進位制位來表示。(實際只需要6個二進位制位)

這個代表32位內'1'位數量的32位二進位制數也就是我們要求的結果。

是不是說得有點羅嗦了- -

這個方法的好處是只需要5步(log n (n=32)),並且沒有迴圈(或分支),流水線不會被打破。

實在太厲害,253一下... 

問一下具體的實現,現在我知道了32bit的好方法: 

void   find32one(int   n)    

但是對於長度是1000萬的0/1輸入,如何實現呢? 

如果用string來儲存每乙個32bit,那效率是不是太低了? 

要不然如何去實現呢?所以我覺得這個演算法的主要開銷在前面, 

而不是32bit的.既然主要開銷在前面,那應該集中去處理 

前面的部分,32bit這裡用移位或者n   &=   (n-1)   就行了. 

大家都怎麼實現把長串分割的呢? 

二進位制 二進位制中1的個數

題目 請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中 1 的個數。例如,把 9 表示成二進位制是 1001,有 2 位是 1。因此,如果輸入 9,則該函式輸出 2。示例 1 輸入 00000000000000000000000000001011 輸出 3 解釋 輸入的二進位制串 0000000...

二進位制1的個數

輸入乙個整數,輸出該數二進位制表示中1的個數。其中負數用補碼表示。可能引起死迴圈的解法 class solution return cnt 由於數字在計算機中的二進位制儲存事實上並不包含符號 也就是 都是統一用補碼表示的。移位操作會保證數的正負不變,當遇到乙個負數,右移到最前面的符號位1時,再往右移...

二進位制位運算中 1 的個數

題目描述 現在夯夯和朱朱餓了,他們想去吃點東西,他們發現店裡東西的 都是2的次方倍 20,21,22 現在夯夯和朱朱想把他們的的錢全都用掉。想知道他們最少能吃多少東西,最多能吃多少東西?輸入格式 多組樣例,每組樣例佔一行,每行乙個整數,代表他們擁有的總錢數。輸出格式 分別回答他們的問題,答案用空格隔...