为什么我们要使用log2来获取最右边的设置位的位置? 我听不懂整个代码在这里。非常感谢!
unsigned int getFirstSetBitPos(int n)
{
return log2(n & -n) + 1;
}
答案 0 :(得分:2)
摘自Wikipedia上的Binary logarithm:
在数学中,二进制对数(log 2 n )是必须将数字2求幂才能获得该值的幂 n 。也就是说,对于任何实数 x
x = log 2 n ⟺2 x = n 。
例如,二进制对数1为0,二进制对数2为1,二进制对数4为2,二进制对数32为5。
因此,在您的代码中,n & -n
首先关闭除最初设置为1的最右边的位以外的所有 位,然后获取日志 2 结果数的>以获得2的幂(恰好与设置为1的位的从0开始的位置相同),最后在结果中加1以得到1位位置(这很奇怪,因为位通常是由从0开始的位置来代替的。)
例如,让我们看一下5
。在二进制中,5是位00000000000000000000000000000101
(假设是32位int
类型),而-5
是位11111111111111111111111111111011
(假设使用2s-complement实现了负整数)。请记住,&
运算符执行bitwise AND
操作,只有在 both 输入中的该位为1
时,该操作才返回给定位的1
。数字,否则返回0
。因此:
00000000000000000000000000000101 (5)
& 11111111111111111111111111111011 (-5)
----------------------------------
00000000000000000000000000000001 (1)
因此,5 & -5 = 1
,然后是log2(1) = 0
和0 + 1 = 1
。
让我们看一个更复杂的数字1041204192
,它是位00111110000011111000001111100000
,而-1041204192
是位11000001111100000111110000100000
:
00111110000011111000001111100000 (1041204192)
& 11000001111100000111110000100000 (-1041204192)
----------------------------------
00000000000000000000000000100000 (32)
所以1041204192 & -1041204192 = 32
,然后是log2(32) = 5
和5 + 1 = 6
。
只是踢一下,让我们看看0
:
00000000000000000000000000000000 (0)
& 00000000000000000000000000000000 (-0)
----------------------------------
00000000000000000000000000000000 (0)
因此0 & -0 = 0
和log2(0)
是-INFINITY
,对于整数,该值未定义。
这里是-1
:
11111111111111111111111111111111 (-1)
& 00000000000000000000000000000001 (--1)
----------------------------------
00000000000000000000000000000001 (1)
所以(-1) & -(-1) = 1
,然后是log2(1) = 0
和0 + 1 = 1
。
还有-2
:
11111111111111111111111111111110 (-2)
& 00000000000000000000000000000010 (--2)
----------------------------------
00000000000000000000000000000010 (2)
所以(-2) & -(-2) = 2
,然后是log2(2) = 1
和1 + 1 = 2
。
依此类推...