There is a lot of information on how to find the next power of 2 of a given value (see refs) but I cannot find any to get the previous power of two.
The only way I f
Here is a one liner for posterity (ruby):
2**Math.log(input, 2).floor(0)
When you work in base 2, you can jump from a power of two to the next one by just adding or removing a digit from the right.
For instance, the previous power of two of the number 8 is the number 4. In binary:
01000 -> 0100 (we remove the trailing zero to get number 4)
So the algorithm to solve the calculus of the previous power of two is:
previousPower := number shr 1
previousPower = number >> 1
(or any other syntax)
This can be done in one line.
int nextLowerPowerOf2 = i <= 0
? 0
: ((i & (~i + 1)) == i)
? i >> 1
: (1 << (int)Math.Log(i, 2));
result
i power_of_2
-2 0
-1 0
0 0
1 0
2 1
3 2
4 2
5 4
6 4
7 4
8 4
9 8
Here's a more readable version in c#, with the <=0 guard clause distributed to the utility methods.
int nextLowerPowerOf2 = IsPowerOfTwo(i)
? i >> 1 // shift it right
: GetPowerOfTwoLessThanOrEqualTo(i);
public static int GetPowerOfTwoLessThanOrEqualTo(int x)
{
return (x <= 0 ? 0 : (1 << (int)Math.Log(x, 2)));
}
public static bool IsPowerOfTwo(int x)
{
return (((x & (~x + 1)) == x) && (x > 0));
}
Solution with bit manipulation only:
long FindLargestPowerOf2LowerThanN(long n)
{
Assert.IsTrue(n > 0);
byte digits = 0;
while (n > 0)
{
n >>= 1;
digits++;
}
return 1 << (digits - 1);
}
Example:
FindLargestPowerOf2LowerThanN(6):
Our Goal is to get 4 or 100
1) 6 is 110
2) 110 has 3 digits
3) Since we need to find the largest power of 2 lower than n we subtract 1 from digits
4) 1 << 2 is equal to 100
FindLargestPowerOf2LowerThanN(132):
Our Goal is to get 128 or 10000000
1) 6 is 10000100
2) 10000100 has 8 digits
3) Since we need to find the largest power of 2 lower than n we subtract 1 from digits
4) 1 << 7 is equal to 10000000
From Hacker's Delight, a nice branchless solution:
uint32_t flp2 (uint32_t x)
{
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x - (x >> 1);
}
This typically takes 12 instructions. You can do it in fewer if your CPU has a "count leading zeroes" instruction.