我想写一个函数,返回最接近的2的次幂数。例如,如果我的输入是789,输出应该是1024。有没有办法不使用任何循环,而只是使用一些位运算符?


当前回答

c#中的可移植解决方案:

int GetNextPowerOfTwo(int input) {
    return 1 << (int)Math.Ceiling(Math.Log2(input));
}

Math.Ceiling(Math.Log2(value))计算2的下一个幂的指数,1 <<通过移位计算实值。

更快的解决方案,如果你有。net Core 3或更高版本:

uint GetNextPowerOfTwoFaster(uint input) {
    return (uint)1 << (sizeof(uint) * 8 - System.Numerics.BitOperations.LeadingZeroCount(input - 1));
}

这将使用system . numbers . bitoperations . leadingzerocount(),如果可用,则使用硬件指令:

https://github.com/dotnet/corert/blob/master/src/System.Private.CoreLib/shared/System/Numerics/BitOperations.cs

更新:

RoundUpToPowerOf2()即将在。net 6!内部实现与上面的. net Core 3解决方案基本相同。

这里是社区更新。

其他回答

如果你需要OpenGL相关的东西:

/* Compute the nearest power of 2 number that is 
 * less than or equal to the value passed in. 
 */
static GLuint 
nearestPower( GLuint value )
{
    int i = 1;

    if (value == 0) return -1;      /* Error! */
    for (;;) {
         if (value == 1) return i;
         else if (value == 3) return i*4;
         value >>= 1; i *= 2;
    }
}
unsigned long upper_power_of_two(unsigned long v)
{
    v--;
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    v++;
    return v;

}

将其转换为浮点数,然后使用.hex()来显示标准化的IEEE表示。

> > >(789)浮动.hex () “0 x1.8a80000000000p + 9”

然后提取指数,再加1。

>>> int(float(789).hex().split('p+')[1]) + 1 10

取2的这个次方。

> > > 2 * * (int (float(789)。hex(),斯普利特(“p +”)[1])+ 1) 1024

next = pow(2, ceil(log(x)/log(2)));

这是通过找到你想要2乘以x的数字来实现的(取这个数字的对数,然后除以想要的底数的对数,详见维基百科)。然后把它四舍五入,得到最接近的整数幂。

这是一个比其他地方链接的按位方法更通用的方法(即更慢!),但很好地了解数学,不是吗?

尽管问题标注为c,我的5分钱。幸运的是,c++ 20将包含std::ceil2和std::floor2(参见这里)。它是consexpr模板函数,目前的GCC实现使用位移位和工作于任何整型无符号类型。