我正在尝试找到在C中计算以下内容的最快方法:
p = 2^(ceil(log2(x)));
到目前为止,看看Stack溢出(以及其他地方)的答案,我已经做到了这一点:
#define LOG2(X) ((int) (8*sizeof (unsigned long long) - __builtin_clzll((X)) - 1))
int p = 1 << LOG2( (unsigned long long)x );
x
将始终为整数(类型int
)且大于零。我从这个stackoverflow question获得了LOG2解决方案。有几个很好的答案,但所有这些似乎都在四舍五入(包括这一个)。我需要围捕。我对修改它们的解决方案不够满意。任何帮助将不胜感激!!!!
答案 0 :(得分:4)
我非常肯定:
2^(ceil(log2(x)))
可以被读作2的最低幂,大于或等于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;
}
相对有效,数据类型中每位数最多需要一次迭代(例如32位整数)。
这将返回正确的2的幂,或者在出错时返回零(如果输入的数字为零,或者结果无法在数据类型中表示)。
您可以在以下程序中看到它的实际效果:
#include <stdio.h>
#include <limits.h>
unsigned int fn (unsigned int x) {
if (x == 0) return 0;
unsigned int result = 1;
while ((result < x) && (result != 0))
result <<= 1;
return result;
}
int main (void) {
printf ("%u -> %u\n\n", 0, fn(0));
for (unsigned int i = 1; i < 20; i++)
printf ("%u -> %u\n", i, fn(i));
printf ("\n%u -> %u\n", UINT_MAX, fn(UINT_MAX));
return 0;
}
输出:
0 -> 0
1 -> 1
2 -> 2
3 -> 4
4 -> 4
5 -> 8
6 -> 8
7 -> 8
8 -> 8
9 -> 16
10 -> 16
11 -> 16
12 -> 16
13 -> 16
14 -> 16
15 -> 16
16 -> 16
17 -> 32
18 -> 32
19 -> 32
4294967295 -> 0
答案 1 :(得分:2)
到底是什么,我会把它作为答案。
要将“向下舍入”转换为“向上舍入”,只需向下舍入计算log(x-1)并将1加到结果中。
一般来说,向上舍入的结果总是比向下舍入1(即floor(某事物)和ceil(某事物)相差1),除非事物是精确整数;在这种情况下,当你的输入是2的幂时。从输入中减去1并将1加到结果中的技巧是通用的;它适用于任何单调函数,如log()。
为了完全正确,您可能希望将特殊情况0作为输入,但对于原始公式也是如此,因为log(0)未定义。