2013-12-11 37 views
2

我想解決一個二元難題,我的策略是轉換零和一個網格,並且我想確保每行都有相同數量的0和1.在Python中獲取零和一個二進制數的個數

有什麼方法可以統計一個數字有多少個1和0,而不需要迭代數字?

什麼我目前做的是:

def binary(num, length=4): 
    return format(num, '#0{}b'.format(length + 2)).replace('0b', '') 

n = binary(112, 8) 
// '01110000' 
and then 
n.count('0') 
n.count('1') 

是否有這樣做的任何更有效的計算(或數學的方式)?

回答

1

如果length是中等(比如小於20),則可以使用列表作爲查找表。

如果您正在進行大量查找,那麼只需要生成該列表,但看起來您可能在這種情況下。

例如。對於0計數的16位表,使用此

zeros = [format(n, '016b').count('0') for n in range(1<<16)] 
ones = [format(n, '016b').count('1') for n in range(1<<16)] 

20位仍需要一秒鐘下產生此計算機上

編輯:此稍快,似乎:

zeros = [20 - bin(n).count('1') for n in range(1<<20)] 
ones = [bin(n).count('1') for n in range(1<<20)] 
+0

你能解釋的範圍(1 << 20)?我不明白它是什麼產生的 – nick

+0

1 << 20是(2 ** 20)-1 –

+0

你不想要範圍從0,20? – nick

3

你在找什麼是一個數字的Hamming weight。在較低級別的語言中,您可能會使用一個漂亮的SIMD within a register技巧或庫函數來計算這一點。在Python,最短和最有效的方法是隻把它變成一個二進制串並計算'1' S:

def ones(num): 
    # Note that bin is a built-in 
    return bin(num).count('1') 

您可以通過數字的總數減去ones(num)取得零的個數。

def zeros(num, length): 
    return length - ones(num) 

示範:

>>> bin(17) 
'0b10001' 
>>> # leading 0b doesn't affect the number of 1s 
>>> ones(17) 
2 
>>> zeros(17, length=6) 
4