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?
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:cis 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 + ccauses carries to ripple through the continuous set bits fromcup until a 1 is carried into a 0.r ^ valtherefore 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 byccauses the bottom bit inr ^ valto be lost to a flooring operation. Sincerhas kept one carry bit, the final Hamming weight ofnextwill 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.