Previous power of 2

后端 未结 11 1415
一整个雨季
一整个雨季 2020-11-30 05:42

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

相关标签:
11条回答
  • 2020-11-30 06:33

    Here is a one liner for posterity (ruby):

    2**Math.log(input, 2).floor(0)
    
    0 讨论(0)
  • 2020-11-30 06:34

    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)

    0 讨论(0)
  • 2020-11-30 06:41

    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));
    }
    
    0 讨论(0)
  • 2020-11-30 06:44

    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 
    
    0 讨论(0)
  • 2020-11-30 06:47

    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.

    0 讨论(0)
提交回复
热议问题