tags:

views:

513

answers:

3

I need to write some logic to determine, given an even number, the highest power of two that evenly divides it. What is the maximum value of 2^n where Input % 2^n == 0?

IE:
Input -> Output

4 (0100) -> 4

8 (1000) -> 8

12 (1100) -> 4

14 (1110) -> 2

24 (11000) -> 8

etc....

It looks like there be some bitwise logic that may work out: when looking at the input in binary, the rightmost one bit appears to be solution. How do I determine this value in C? Is there another solution that may be easier?

Thanks- Jonathan

+4  A: 

Without using floating point arithmetic:

((x ^ (x - 1)) >> 1) + 1

Simplification and edge cases are left as exercises for the reader.

Greg Hewgill
X = 24(24 ^ 23) = 2462324623 >> 1 = 1231112311 + 1 = 12312Did I compute something wrong?
Jonathan: `^` is XOR, so `(24 ^ 23)` is 15.
caf
BTW, if x is unsigned then I believe the only edge case which needs special handling is zero.
caf
+10  A: 

If you are willing to assume 2's complement arithmetic:

x & -x

If you do a lot of this sort of thing (or even if you just find it interesting), find yourself a copy of the book "Hacker's Delight".

edit: avakar correctly notes that this doesn't depend on 2's complement if the type is unsigned. The relevant section of the standard is §6.2.5, paragraph 9:

A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

"one greater than the largest value" leaves some wiggle room for an especially perverse implementation (in particular, an implementation that doesn't use binary, for example), but you're pretty unlikely to encounter that.

Stephen Canon
very concise, I like!
Charles Ma
+1. For the record, you don't have to assume 2's complement. This will work portably on any architecture, as long as `x` is of unsigned arithmetic type.
avakar
Stephen Canon
`(~x + 1)` is two's-complement negation, that is.
Stephen Canon
No. For `x` unsigned, `-x` will be `2^k-x` for some `k`. In your example, `k` will be 32 and `-x` will be `0xffffffff`. Again, `unsigned` is the key here, all bets are off for signed `x`.
avakar
+3  A: 

We can replace (-x) by (~x + 1):

x & (~x+1)

Low Level Bit Hacks You Absolutely Must Know provides detailed explanation.

J.F. Sebastian
John R. Strohm