C:快速指数(幂2)+整数的二进制对数(舍入为)

时间:2015-05-28 02:11:50

标签: c math casting bit-manipulation

我正在尝试找到在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解决方案。有几个很好的答案,但所有这些似乎都在四舍五入(包括这一个)。我需要围捕。我对修改它们的解决方案不够满意。任何帮助将不胜感激!!!!

2 个答案:

答案 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)未定义。