2

Given a certain integer x, I wish to compute the next higher integer y which has a certain hamming weight w. Mind that the hamming weight of x does not have to be w as well.

So, for example x = 10 (1010) and w = 4 the result should be y = 15 (1111).

Obviously, I could achieve this by just incrementing x but that would be a very slow solution for high numbers. Can I achieve this by the means of bit shifts somehow?

l3moony
  • 65
  • 4

1 Answers1

2

There are three cases: the Hamming weight (a.k.a. bitwise population count) is reduced, unchanged, or increased.

Increased Hamming weight

Set enough successive low-order 0-bits to achieve the desired weight.

This works because each successive low-order bit is the smallest value that you can add, and their sum is the smallest difference that will sufficiently increase the Hamming weight.

Unchanged Hamming weight

  1. Add the value of the lowest-order 1-bit.
  2. Increase the Hamming weight per above, if necessary.

This works because the value of the lowest set bit is the lowest value that will cause a carry to occur. Adding any lower bit-value would simply set that bit, and increase the Hamming weight.

As long as addition "carries a one," bits will be cleared. The resulting weight must be the equal or reduced. If several bits are cleared due to a chain of carries, you'll need to increase the weight in compensation by setting low-order bits.

Reduced Hamming weight

  1. Clear enough low-order 1-bits to achieve the new desired weight.
  2. Follow the above process for unchanged weight.

This works because clearing low-order 1-bits finds the preceding number with the desired weight, by subtracting the smallest viable amount. From the preceding number of the correct weight, follow the "unchanged weight" algorithm to reach the next number.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • Your algorithm for reduction doesn't work in all cases. Consider x = 00111, w=2. The answer should be 01001, but your algorithm gives 01100. – Oliver Charlesworth Jul 14 '15 at 02:44
  • @OliverCharlesworth Thanks. Fixed. – Potatoswatter Jul 14 '15 at 02:58
  • Cool, I can more-or-less convince myself that this works now. What would make this answer complete, though, is a proof/rationale for why it works (similar to my inductive argument below). Specifically, it's immediately obvious that this achieves the desired weight, but it takes some work to see that it always produces the smallest value that's > x. – Oliver Charlesworth Jul 14 '15 at 12:04
  • Looks great, my answer is now definitively superseded! – Oliver Charlesworth Jul 14 '15 at 13:04
  • By now I have developed a working algorithm. I will post it after I have found the time to clean it up a little bit – l3moony Jul 15 '15 at 08:05