java - 为什么这个算法使用Java中的按位与运算符?

标签 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 & -i);)作者的意思是根据最低有效位在 block 数组中选择一个元素编号 i。

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

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

最佳答案

是的,你可以做到。一些合理的解释:

  • 原始版本移植到了具有自制版本的东西,他把这个技巧留在那里。
  • 不明白 Integer.numberOfTrailingZeros() 不关心是否还有其他有效位,并且知道如何快速获取最高有效位的值。
  • 或者最初有一个自制版本,只是使用 i 和 -i 并进行位移,直到值为零并将其设置为等于 t。有人只是用内置操作替换了该操作,却没有意识到 i & -i 是一个技巧,使删除的操作有效。对零进行检查比其他检查要快,尽管它不再那么重要了,因此一些 super 优化人员经常会安排一些事情来对零进行检查,特别是如果他们不需要做减法的话。

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

i & -i 返回 2 补码的二进制表示形式,也就是说翻转所有位并加 1。因此,最终只会得到进位的二进制金额。然后您可以确定二进制表示形式中 1 后面有多少个零。通常通过位移直到找到 1,位移的数量是该数字在最低有效位置有多少个零。这可用于进行位移,直到得到零。尽管该代码的 Integer 版本不需要它。

关于java - 为什么这个算法使用Java中的按位与运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41798008/

相关文章:

java - GWT 日志记录仅显示级别 SERVE

java - 字节数组到字符串并返回.. -127 的问题

java - BufferedReader 连接未关闭

java - 新鲜的Springboot项目无法启动,原因是: java. lang.ClassNotFoundException : javax. persistence.EntityManagerFactory

algorithm - Count-Min Sketch 和 Heavy-Hitters 问题

algorithm - 需要一些卡片替换算法的想法

java - JDBC preparedStatement.executeBatch() 的终止条件

algorithm - 面试题——在未排序的数组中找到第 KTH 个最小的元素

algorithm - 这个(选择排序)算法的运行时间是如何计算的?

algorithm - 后续和