C:快速求幂(幂2)和#x2B;整数的二进制对数(向上舍入)
我试图找到用C计算以下内容的最快方法:C:快速求幂(幂2)和#x2B;整数的二进制对数(向上舍入),c,math,casting,bit-manipulation,C,Math,Casting,Bit Manipulation,我试图找到用C计算以下内容的最快方法: p = 2^(ceil(log2(x))); 到目前为止,看看堆栈溢出(和其他地方)中的答案,我已经得出了以下结论: #define LOG2(X) ((int) (8*sizeof (unsigned long long) - __builtin_clzll((X)) - 1)) int p = 1 << LOG2( (unsigned long long)x ); #定义LOG2(X)((int)(8*sizeof(unsigned l
p = 2^(ceil(log2(x)));
到目前为止,看看堆栈溢出(和其他地方)中的答案,我已经得出了以下结论:
#define LOG2(X) ((int) (8*sizeof (unsigned long long) - __builtin_clzll((X)) - 1))
int p = 1 << LOG2( (unsigned long long)x );
#定义LOG2(X)((int)(8*sizeof(unsigned long-long)-(X))-1))
int p=1见鬼,我来回答这个问题
要将“向下舍入”转换为“向上舍入”,只需计算向下舍入的日志(x-1)并将1添加到结果中
通常,向上舍入的结果总是比向下舍入的结果多1(即地板(某物)和天花板(某物)相差1),除非某物是一个精确的整数;在这种情况下,当您的输入是2的幂时。从输入中减去1,然后在结果中加1的技巧是普遍的;它适用于任何单调函数,如log()
为了完全正确,您可能希望将特例0作为输入,但对于原始公式也是如此,因为log(0)未定义。见鬼,我会回答这个问题
要将“向下舍入”转换为“向上舍入”,只需计算向下舍入的日志(x-1)并将1添加到结果中
通常,向上舍入的结果总是比向下舍入的结果多1(即地板(某物)和天花板(某物)相差1),除非某物是一个精确的整数;在这种情况下,当您的输入是2的幂时。从输入中减去1,然后在结果中加1的技巧是普遍的;它适用于任何单调函数,如log()
为了完全正确,您可能希望将特例0作为输入,但对于原始公式也是如此,因为log(0)未定义。我非常确定:
2^(ceil(log2(x)))
可以读取为大于或等于x
的两个值的最小幂,但x
为零的值未定义除外
在这种情况下,可以通过以下方式找到:
unsigned int fn (unsigned int x) {
if (x == 0) return 0;
unsigned int result = 1;
while ((result < x) && (result != 0))
result <<= 1;
return result;
}
我非常肯定:
2^(ceil(log2(x)))
可以读取为大于或等于x
的两个值的最小幂,但x
为零的值未定义除外
在这种情况下,可以通过以下方式找到:
unsigned int fn (unsigned int x) {
if (x == 0) return 0;
unsigned int result = 1;
while ((result < x) && (result != 0))
result <<= 1;
return result;
}
谢谢你的快速回答。我本来可以自己想出来的(掌心)。顺便问一下,我的解决方案还有什么问题吗?任何可预见的可移植性问题?内置clzll
是一个GCC扩展。几乎可以肯定的是,Clang和英特尔C编译器支持它,但我不了解微软。此外,最终结果可以大于int
。在任何情况下,当输入大于2^63时,它都可能溢出。。。基本上,我建议仔细考虑边界情况(x=0,x非常大)。确保“计算日志(x-1)向下取整并添加1”适用于2的精确幂,如1,2,4?@chux:对于2,4,8,…,是的,我确信它适用。对于x=1,我认为它会失败,因为0未定义\uuuuu builtin\uclzll
(请参阅)。因此,对于这个解决方案,需要使用特例x=1。它应该仍然比循环快得多,至少在x86上是这样,因为clz(又名.bsr)是一条单指令。感谢您的快速回答。我本来可以自己想出来的(掌心)。顺便问一下,我的解决方案还有什么问题吗?任何可预见的可移植性问题?内置clzll
是一个GCC扩展。几乎可以肯定的是,Clang和英特尔C编译器支持它,但我不了解微软。此外,最终结果可以大于int
。在任何情况下,当输入大于2^63时,它都可能溢出。。。基本上,我建议仔细考虑边界情况(x=0,x非常大)。确保“计算日志(x-1)向下取整并添加1”适用于2的精确幂,如1,2,4?@chux:对于2,4,8,…,是的,我确信它适用。对于x=1,我认为它会失败,因为0未定义\uuuuu builtin\uclzll
(请参阅)。因此,对于这个解决方案,需要使用特例x=1。它应该仍然比循环快得多,至少在x86上是这样,因为clz(又名.bsr)是一条单指令。如果该x
是一个int
或x
是一个带整数值的FP?@chux澄清了它。它将始终是int类型。顺便说一句,如果您重视可移植性,我认为您可能应该使用CHAR\u BIT
,而不是8
,尽管使用内在函数可能会使这一点变得不那么重要:-)请在您的条件下明确“x将始终是一个整数”。如果该x
是一个int
或x
是一个带整数值的FP?@chux澄清了它。它将始终是int类型。顺便说一下,如果您重视可移植性,我认为您可能应该使用CHAR\u BIT
而不是8
,尽管使用内在函数可能会使其不那么重要:-)关于“2^(cel(log2(x))”代表的内容,您是对的。你是正确的解决方案(显然)。我不确定它是否会比我所拥有的更快(我可能会在以后运行这两个程序来找出答案)。不管怎么说,这仍然是一个非常简洁直观的解决方案(对它竖起大拇指)。Thanks@Haider,它可能不会比您已经为具有\uuuu内置
内在特性的平台提供的解决方案快,但它可能会更好地适用于那些没有这样做的平台:-)关于“2^(ceil(log2(x))”代表的内容,您是对的。你是正确的解决方案(显然)。我不确定它是否会比我所拥有的更快(我可能会在以后运行这两个程序来找出答案)。不管怎么说,这仍然是一个非常简洁直观的解决方案(对它竖起大拇指)。Thanks@Haider,它可能不会比您已经为具有\uuuuu内置
内在特性的平台提供的解决方案快,但它可能会更好地适用于那些不具有内在特性的平台:-)