Counting the number of set bits in a number
<p>The problem statement is: </p>

<p>Write an efficient program to count number of 1s in binary representation of an integer.</p>

<p>I found a post on this problem <a href="http://www.geeksforgeeks.org/count-set-bits-in-an-integer/" rel="nofollow">here</a> which outlines multiple solutions which run in log(n) time including Brian Kernigan's algorithm and the gcc <code>__builtin_popcount()</code> method.</p>

<p>One solution that wasn't mentioned was the python method: <code>bin(n).count("1")</code> 
which also achieves the same effect. Does this method also run in log n time?</p>

<p>You are converting the integer to a string, which means it'll have to produce N <code>'0'</code> and <code>'1'</code> characters. You then use <code>str.count()</code> which must visit <em>every character</em> in the string to count the <code>'1'</code> characters.</p>

<p>All in all you have a O(N) algorithm, with a relatively high constant cost.</p>

<p>Note that this is the same complexity as the code you linked to; the integer <code>n</code> has log(n) bits, but the algorithm still has to make N = log(n) steps to calculate the number of bits. The <code>bin(n).count('1')</code> algorithm is thus equivalent, but <em>slow</em> as there is a high cost to produce the string in the first place.</p>

<p>At the cost of a table, you could move to processing integers <em>per byte</em>:</p>

<pre><code>table = [0]
while len(table) &lt; 256:
    table += [t + 1 for t in table]

length = sum(map(table.__getitem__, n.to_bytes(n.bit_length() // 8 + 1, 'little')))
</code></pre>

<p>However, because Python needs to produce a series of new objects (a <code>bytes</code> object and several integers) this method never quite is fast enough to beat the <code>bin(n).count('1')</code> method:</p>

<pre><code>&gt;&gt;&gt; from random import choice
&gt;&gt;&gt; import timeit
&gt;&gt;&gt; table = [0]
&gt;&gt;&gt; while len(table) &lt; 256:
...     table += [t + 1 for t in table]
...
&gt;&gt;&gt; def perbyte(n): return sum(map(table.__getitem__, n.to_bytes(n.bit_length() // 8 + 1, 'little')))
...
&gt;&gt;&gt; def strcount(n): return bin(n).count('1')
...
&gt;&gt;&gt; n = int(''.join([choice('01') for _ in range(2 ** 16)]))
&gt;&gt;&gt; for f in (strcount, perbyte):
...     print(f.__name__, timeit.timeit('f(n)', 'from __main__ import f, n', number=1000))
...
strcount 1.11822146497434
perbyte 1.4401431040023454
</code></pre>

<p>No matter the bit-length of the test number, <code>perbyte</code> is always a percentage slower.</p>

python algorithm bit-manipulation