【问题标题】:How does this program actually work?这个程序实际上是如何工作的?
【发布时间】:2015-02-08 01:07:45
【问题描述】:

我写了一个递归方法,它接受一个数字,并返回二的下一个幂。如果输入的数字是 2 的幂,它将映射到自身。这假定 n > 0

static int nextPower1(int n) {
    if(n == 0) {
        System.out.println("nextPower(" + n + ") = 2");
        return 2;
    } else if(n == 1) {
        System.out.println("nextPower(" + n + ") = 1");
        return 1;
    } else {
        int lastBit = n & 1;
        int secondLastBit = (n >> 1) & 1;
        int restOfTheBits = (n >> 2);

        int result = nextPower1(restOfTheBits << 1 | secondLastBit ^ lastBit);
        return result << 1;
    }

我不明白的是,对最后两位进行异或并设置倒数第二位如何返回正确的二的幂?这个按位技巧是如何工作的?


大编辑:

好的,我知道哪里出了问题,通过更新基本案例并将 XOR 更改为 OR,我认为它已修复。 我把它放在一个循环中来测试它。循环检查 2 从 Integer.MAX_VALUE 到 Integer.MAX_VALUE 的幂。它从 Integer.MIN_VALUE 返回了至少 (1

static int nextPower2(int n) {
    if(n == 3) {
        return 4;
    } else if(n < 4) {
        return 1 << (n >> 1);
    } else {
        return nextPower(((n >> 2) << 1) | ((n >> 1) & 1) | (n & 1)) << 1;
    }
}

【问题讨论】:

  • Power of 2 formula help 的可能重复项
  • 您在不了解 xoring 的工作原理的情况下编写了此代码?我在这里有点困惑。
  • “这假定 n > 0”。那你为什么要把 n=0 的结果编码为 2 呢?不应该是 2 次方 0 = 1 吗?
  • 此代码不正确。它返回 4 作为 7 的 2 的下一个幂。它返回 8 代表 13 和 14。
  • 为 n=1 返回 1 使代码正确。

标签: java binary bit-manipulation


【解决方案1】:

此代码已损坏,它总是返回错误的答案,例如一个 1 后跟一个或多个零,后跟两个 1:1011、10011 等。 (因为当它递归时,它将成对的 1 组合成一个 0,它来自 这一点使它与传入的 1000、10000 等无法区分)

(编辑:对于所有具有偶数个 1 位的值来说,这是错误的 msb的权利。每对异或为 0,丢失必要的信息 以获得正确的结果。 - AR。)

递归循环将最低有效位滚动到数字中 作为卷起部分是否包含任何 1 的历史记录。 隔离两个最不重要的位只会使代码更难理解; 它正在做otherBits = n &gt;&gt; 1; return nextPower1(otherBits ^ lastBit)

查看剩下的最后两位(最重要的位和 卷起历史位),如果历史为零,则最高有效位 是唯一设置的位,它本身是 2 的下一个幂。如果历史位 然而,是一,那么二的下一个幂是下一位位置,一 过去的msb。 (如果只有历史记录位工作正常;见下文)

代码不是查看最后两位,而是查看 msb 和历史位。如果为 1,则仅设置 msb,history 为零,并返回 1(自身)作为 2 的幂。如果为 0,那么历史位是 设置,并返回下一个更高的幂 (2)。随着递归展开, 功率(1 或 2)被移回原来的 msb 位置,产生 msb 或二的下一个更大的幂。

但是,由于历史不会通过零传播,因此会中断。

要修复,递归需要修复历史记录(使用 OR,而不是 XOR),并且 最后不要将历史位混合到 msb 中,例如:

nextPower( int n ) {
    if (n == 1) return 1;
    if (n == 2) return 2;
    if (n == 3) return 4;
    return nextPower((n >> 1) | (n & 1)) << 1;
}

(测试 (n==0) 以支持 n >= 0,代码明确不支持)

【讨论】:

  • n=0 的返回值更改为 1 时代码工作
  • 没有; if (n==0) return 1 使 3, 4, 5, 6 产生 2, 4, 4, 4(n==0 处理“有 lsbits”的情况;返回 1 返回 msb,就好像 n 是 2 的偶数幂一样)跨度>
  • 你是对的。刚刚检查并通过一个小修复使其工作,虽然不是很优雅。
  • 正如你所说,你的代码需要一个检查来处理零,这也将被放置在一个辅助函数中。
【解决方案2】:

如下修复代码使其工作(见http://ideone.com/P5s4rd):

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        int n;
        int result;
        for (n=0;n<=16;n++) {
            result = nextPower(n);
            System.out.println("Next power of " + n + " is " + result);
        }
    }

    static int nextPower(int n) {
        int result;
        result = nextPower1(n);
        if (n<=1 || result ==n)
            return result;
        else
            return result * 2;
    }


    static int nextPower1(int n) {
        if(n == 0) {
            return 1;
        } else if(n == 1) {
            return 1;
        } else {
            int lastBit = n & 1;
            int secondLastBit = (n >> 1) & 1;
            int restOfTheBits = (n >> 2);

            int result = nextPower1(restOfTheBits << 1 | secondLastBit ^ lastBit);
            return result << 1;
        }
    }
}

你得到以下输出:

Next power of 0 is 1 (0 <= 2 power 0)
Next power of 1 is 1 (1 <= 2 power 0)
Next power of 2 is 2 (2 <= 2 power 1)
Next power of 3 is 4 (3 <= 2 power 2)
Next power of 4 is 4 ...etc
Next power of 5 is 8
Next power of 6 is 8
Next power of 7 is 8
Next power of 8 is 8
Next power of 9 is 16
Next power of 10 is 16
Next power of 11 is 16
Next power of 12 is 16
Next power of 13 is 16
Next power of 14 is 16
Next power of 15 is 16
Next power of 16 is 16

【讨论】:

  • 是的,有效 -- 助手计算 n 的 msb,如果 n 是 2 的幂,则 n == msb(n),否则返回下一个更高的幂 (2*msb, = = msb(2*n))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
  • 1970-01-01
  • 2012-06-07
  • 1970-01-01
  • 2014-10-24
  • 2019-07-04
  • 1970-01-01
相关资源
最近更新 更多