我需要计算2的最大功率,即<整数值,x
目前我正在使用:
#define log2(x) log(x)/log(2)
#define round(x) (int)(x+0.5)
x = round(pow(2,(ceil(log2(n))-1)));
这是一个性能关键功能
是否有一种计算效率更高的计算方法?
答案 0 :(得分:3)
您实际上是在寻找数字中最高的非零位。许多处理器都有内置的指令,而这些指令又由许多编译器公开。例如,在GCC中,我会查看__builtin_clz
,其中
从最高有效位开始,返回
x
中前导0位的数量。
与sizeof(int) * CHAR_BIT
和移位一起,您可以使用它来计算相应的纯二次幂整数。还有一个长整数的版本。
(CPU指令可能被称为“CLZ”(计数前导零),以防您需要查看其他编译器。)
答案 1 :(得分:2)
基于Sean Eron Anderson的Bit Twiddling Hacks: Find the log base 2 of an N-bit integer in O(lg(N)) operations(由Eric Cole和Andrew Shapira提供的代码):
unsigned int highest_bit (uint32_t v) {
unsigned int r = 0, s;
s = (v > 0xFFFF) << 4; v >>= s; r |= s;
s = (v > 0xFF ) << 3; v >>= s; r |= s;
s = (v > 0xF ) << 2; v >>= s; r |= s;
s = (v > 0x3 ) << 1; v >>= s; r |= s;
return r | (v >> 1);
}
返回输入最高位的索引; 2的最大幂不大于输入1 << highest_bit(x)
,因此2的最大幂大于输入,因此只是1 << highest_bit(x-1)
。
对于64位输入,只需将输入类型更改为uint64_t
,并在函数开头添加以下额外行,在变量声明之后:
s = (v > 0xFFFFFFFF) << 8; v >>= s; r |= s;
答案 2 :(得分:2)
我的c-libutl库中有一个整数log2函数(如果有人有兴趣,可以在googlecode上托管)
/*
** Integer log base 2 of a 32 bits integer values.
** llog2(0) == llog2(1) == 0
*/
unsigned short llog2(unsigned long x)
{
long l = 0;
x &= 0xFFFFFFFF /* just in case 'long' is more than 32bit */
if (x==0) return 0;
#ifndef UTL_NOASM
#if defined(__POCC__) || defined(_MSC_VER) || defined (__WATCOMC__)
/* Pelles C MS Visual C++ OpenWatcom */
__asm { mov eax, [x]
bsr ecx, eax
mov l, ecx
}
#elif defined(__GNUC__)
l = (unsigned short) ((sizeof(long)*8 -1) - __builtin_clzl(x));
#else
#define UTL_NOASM
#endif
#endif
#ifdef UTL_NOASM /* Make a binary search.*/
if (x & 0xFFFF0000) {l += 16; x >>= 16;} /* 11111111111111110000000000000000 */
if (x & 0xFF00) {l += 8; x >>= 8 ;} /* 1111111100000000*/
if (x & 0xF0) {l += 4; x >>= 4 ;} /* 11110000*/
if (x & 0xC) {l += 2; x >>= 2 ;} /* 1100 */
if (x & 2) {l += 1; } /* 10 */
return l;
#endif
return (unsigned short)l;
}
然后你可以简单地计算
(1 << llog2(x))
计算小于x的2的最大幂。当心0!你应该单独处理它。
它使用汇编代码,但也可以通过定义UTL_NOASM符号强制为纯C代码。
该代码当时已经过测试,但很长一段时间我没有使用它,我不能说它是否在64位环境中运行。
答案 3 :(得分:0)
转移位置很可能会快得多。可能一些比特的二分法可以使它更快。很好的运动,以改善。
#include <stdio.h>
int closestPow2(int x)
{
int p;
if (x <= 1) return 0; /* No such power exists */
x--; /* Account for exact powers of 2, then one power less must be returned */
for (p = 0; x > 0; p++)
{
x >>= 1;
}
return 1<<(p-1);
}
int main(void)
{
printf("%x\n", closestPow2(0x7FFFFFFF));
return 0;
}
答案 4 :(得分:0)
左右移位操作符最佳
int MaxPowerOf2(int x)
{
int out = 1;
while(x > 1) { x>>1; out<<1;}
return out;
}
答案 5 :(得分:0)
#include <math.h>
double greatestPower( double x )
{
return floor(log( x ) / log( 2 ));
}
自单log
单调递增函数以来就是如此。