关于整数i += (i&(-i))代码功能的技术问询
解析代码
i += (i&(-i))的功能 首先得纠正你一开始的误解:这段代码绝对不是计算绝对值的优化方式,你对C负数存储的怀疑是对的——C里负数用补码存储,不是简单翻转某一位,补码的规则是“负数的补码等于其绝对值的二进制取反后加1”,这个细节恰恰是理解这段代码的关键。
先拆解核心部分i&(-i)的作用:
- 当
i是正数时,-i的补码是~i + 1,把它和i做按位与运算,结果会是i的二进制表示中最右边的1所对应的数值。比如i=6(二进制000...0000110),-i的补码是111...1111010,按位与后得到000...0000010(也就是2)。 - 当
i是负数时,-i是正数,同样的逻辑,i&(-i)依然会提取出i补码中最右边的1对应的正数数值。比如i=-6(补码111...1111010),-i=6(000...0000110),按位与结果还是2。
那i += (i&(-i))整体做了什么?我们用几个例子直观感受:
- 初始
i=3(二进制11):第一次执行后i=3+1=4(100);第二次执行i=4+4=8(1000);第三次变成16,以此类推,直到32位整数溢出。 - 初始
i=5(101):第一次i=5+1=6(110);第二次i=6+2=8(1000);之后同样逐步变成更大的2的幂次。 - 初始
i=-6:第一次i=-6+2=-4(补码111...1111100);第二次i=-4+4=0;之后i就不再变化了。
放在for循环的递增部分时,这个循环就不再是逐个遍历整数,而是每次跳跃到将当前数最右边的1“进位”后的数值,最终会逐步逼近(正数情况)或归零(负数情况)。这种操作一般用在和二进制位操作相关的算法里,比如数位统计、分治类的位运算场景,用来高效地遍历特定的数值序列。
内容的提问来源于stack exchange,提问作者botiapa
相关产品推荐
相关产品推荐

