It's easy to generate numbers that have one non-zero digit in their binary representation, and it's not much harder to generate numbers with two non-zero digits. It rapidly seems to become more difficult, though. Is there a general formula that will let me generate all numbers of all lengths with (say) 7 non-zero digits, starting with 1111111 and continuing indefinitely?
If there isn't a general formula, is there a standard algorithm?
Best Answer
There is an algorithm: how standard it is I couldn't tell you, but it's well enough known that I learnt it as an undergrad in computer science. It's due to Bill Gosper and it transforms a number into the next largest number with the same Hamming weight using (twos complement) arithmetic and bitwise operations. Input
val
, outputnext
, code (with suitable types) is valid in most languages related to C, although some may need>>>
instead of>>
for right shift without sign extension:c
is the least power of 2 in the binary representation ofval
: this relies on twos complement, since to negate an integer you invert its bits and add 1.val + c
causes carries to ripple through the continuous set bits fromc
up until a 1 is carried into a 0.r ^ val
therefore gives a value equal to twice the value of the lowest continuous block of set bits inval
. Shifting right 2 is equivalent to division by 4, and then dividing also byc
causes the bottom bit inr ^ val
to be lost to a flooring operation. Sincer
has kept one carry bit, the final Hamming weight ofnext
will therefore be the same as inval
, and if this explanation is clear enough then it should be obvious that it's the lexicographically next value with that property.