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


当前回答

将其转换为浮点数,然后使用.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

其他回答

如果您正在使用GCC,您可能想要看看Lockless Inc.优化next_pow2()函数。本页描述了一种使用内置函数builtin_clz()(计数前导零)的方法,然后直接使用x86 (ia32)汇编指令bsr(位扫描反向),就像它在另一个答案的游戏开发站点链接中所描述的那样。此代码可能比前面的回答中描述的更快。

顺便说一下,如果你不打算使用汇编指令和64位数据类型,你可以使用这个

/**
 * return the smallest power of two value
 * greater than x
 *
 * Input range:  [2..2147483648]
 * Output range: [2..2147483648]
 *
 */
__attribute__ ((const))
static inline uint32_t p2(uint32_t x)
{
#if 0
    assert(x > 1);
    assert(x <= ((UINT32_MAX/2) + 1));
#endif

    return 1 << (32 - __builtin_clz (x - 1));
}

这是我用c语言的解决方案,希望能有所帮助!

int next_power_of_two(int n) {
    int i = 0;
    for (--n; n > 0; n >>= 1) {
        i++;
    }
    return 1 << i;
}
from math import ceil, log2
pot_ceil = lambda N: 0x1 << ceil(log2(N))

测试:

for i in range(10):
    print(i, pot_ceil(i))

输出:

1 1
2 2
3 4
4 4
5 8
6 8
7 8
8 8
9 16
10 16

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解决方案基本相同。

这里是社区更新。

许多处理器架构都支持log以2为底或非常类似的操作——计数前导零。许多编译器都有针对它的内在特性。参见https://en.wikipedia.org/wiki/Find_first_set