为什么这个算法在Java中使用bitwise和operator?

时间:2017-01-23 01:22:49

标签: java algorithm

我看到了一个算法,如:

    for (int i = 1; i < sums.length; i++) {
        /*
         * dynamic programming:
         * 1. remove a single block from the current subset of blocks
         * 2. the corresponding block sum was already calculated
         * 3. add the number on the removed block to it
         *
         * here: always choose the block corresponding
         * to the least significant bit of i
         */
        int t = Integer.numberOfTrailingZeros(i & -i);
        sums[i] = sums[i & ~(1 << t)] + block[t];

        //only add block subsets that add up to a face
        if (masks.containsKey(sums[i]))
            masks.get(sums[i]).add(i);
    }

根据评论,在这一行( int t = Integer.numberOfTrailingZeros(i&amp; -i); )中,作者意味着根据最不重要的意义在块数组中选择一个元素数字i的一点。

为什么作者在i和-i上使用按位和运算符?他们不能只使用我(例如, Integer.numberOfTrailingZeros(i))?

以下是更大的上下文代码:http://pastebin.com/YB9wsdgD

1 个答案:

答案 0 :(得分:2)

是的,你可以做到。几个看似合理的解释:

  • 原始版本已移植到具有家庭酿造版本的东西,并且他将该技巧留在那里。
  • 没有理解Integer.numberOfTrailingZeros()并不关心是否有其他有效位并且知道如何快速获得最重要的位值。
  • 或者最初有一个家庭酿造版本刚刚使用i&amp; -i和bitshifted直到值为零并设置为等于t。有人刚刚用内置的方式取代了那个操作而没有实现i&amp; -i是一个技巧,使删除的操作工作。检查零比其他检查更快,虽然它不再重要,所以一些超优化人员经常安排检查零,特别是如果他们不必减去。

&#13;
&#13;
for (var i = 0; i < 1000; i++) {
  document.write(i & -i);
  document.write('<br>');
}
&#13;
&#13;
&#13;

i&amp; -i返回2s补码的二进制表示,即翻转所有位并加1。因此,它最终将只有二进制数量的进位。然后,您可以确定在二进制表示中1之后有多少个零。通常通过比特移位直到找到1,并且位移的数量是该数字在最不重要的位置具有多少个零。这可以用于比特移位直到你有零。虽然该代码的整数版本并不需要它。