int64_t lstbt(int64_t val){
int64_t msk = val&(val-1);
return log2(val^msk);
}
msk
实际计算什么,为什么我们要返回log
值xor
msk
?
要理解函数:
int64_t lstbt(int64_t val){
int64_t msk = val&(val-1);
return log2(val^msk);
}
让我们把它分成更小的块。
首先语句val-1
,通过将-1
添加到val
,你翻转(除其他外)最小有效位(LSB),(即0
变成1
,反之亦然)。
下一个操作(val&(val-1)
)按位应用"and"。从&
运算符中我们知道:
1 & 1 -> 1
1 & 0 -> 0
0 & 1 -> 0
0 & 0 -> 0
所以要么
val
最初是...0
,val - 1
是....1,在这种情况下val&(val-1)
产生...0
;或者
var
最初是...1
,var - 1
是....0,在本例中val&(val-1)
产生...0
;。
因此,在这两种情况下,val&(val-1)
都设置为0
var
LSB
。除此之外,val&(val-1)
所做的另一个重要更改是设置为0
最右边的第一个位设置为1
.
因此,假设 val = xxxxxxxx 1 0000(只要它显示最右边设置为1的最位,就可以xxxxxxxxx1000
),当msk=val&(val-1)
时,msk
将被xxxxxxxx00000
接下来,我们有val ^ msk
;一个XOR
位运算,我们知道:
1 ^ 1 -> 0
1 ^ 0 -> 1
0 ^ 1 -> 1
0 ^ 0 -> 0
所以因为val
会像xxxxxxxx10000
和 mskxxxxxxxx00000
,其中用val
的 'x' 表示的位将与msk
的位完全匹配;val ^ msk
的结果将始终是一个数字,所有位都设置为0
除了唯一在val
和msk
之间不同的bit
, 即最右边设置为val
1
。
因此,val ^ msk
的结果将始终是 2 的幂值(val
为 0 时除外)。可以用2^y = x
表示的值,其中y
是设置为1的最右位的索引val
,x
是val^msk
的结果。因此,log2(val^msk)
返回y
,即最右边位的索引设置为 1 inval
。
val&(val-1) # to figure out if value is either 0 or an exact power of two.
val^msk # cuts the part of power of 2 from val
log2 # finds the index of bit which set val^msk.
所以我想你lstbt
的功能是找出val
可以在提醒 2 上除以多少次 0。