求一个数取log2的较小的整数 Ilog2

最近在看recast&detour源码的时候有遇到许多数学上的算法问题,特此记录,以便以后查看。


举例:

Ilog2(8) = 3

Ilog2(15) = 3

Ilog2(16) = 4

思路:

从二进制角度看 即 右移几位 以后为1(最高位)

比如

8 = 1000b, 右移3位

15=1111b,右移3位

16=10000b,右移4位

源码:

inline unsigned int dtIlog2(unsigned int v)
{
	unsigned int r;
	unsigned int shift;
	r = (v > 0xffff) << 4; v >>= r;
	shift = (v > 0xff) << 3; v >>= shift; r |= shift;
	shift = (v > 0xf) << 2; v >>= shift; r |= shift;
	shift = (v > 0x3) << 1; v >>= shift; r |= shift;
	r |= (v >> 1);
	return r;
}

解析:

应用二分法的思想,将数进行移位。记 r 为需要右移的位数。

1)将此数与 0xffff 比较

        如果比 0xffff 大,说明至少需要右移16位;r = 16(即1<<4 = 10000b);并将此数右移16位进行更新。

        如果比 0xffff 小,什么都不做;r = 0。

2)将更新后的数与 0xff 比较

        如果比 0xff 大,说明至少需要右移8位;r += 8(即1<<3 = 1000b);并将此数右移8位进行更新。

        如果比 0xff 小,什么都不做;r += 0。

3)将更新后的数与 0xf(1111b)比较

        如果比 0xf 大,说明至少需要右移4位;r += 4(即1<<2 = 100b);并将此数右移4位进行更新。

        如果比 0xf 小,什么都不做;r += 0。

4)将更新后的数与 0x3(11b)比较

        如果比 0x3 大,说明至少需要右移2位;r += 2(即1<<1 = 10b);并将此数右移2位进行更新。

        如果比 0x3 小,什么都不做;r += 0。

5)将更新后的数(只剩下两个bit位 XXb )直接右移一位

        如果结果为1,r+=1。

        如果结果为0,r+=0。

        r即为最终结果。

  ps:此处 |= 即为 +=, 使用位运算更高效。 即 10000b | 1000b = 10000b + 1000b。 

参考:

https://github.com/recastnavigation/recastnavigation

你可能感兴趣的:(数学)