我怎样才能得到位的位置

时间:2015-05-25 00:36:27

标签: java algorithm binary bit-manipulation

我有一个十进制数,我需要转换为二进制数,然后在二进制表示中找到一个的位置。

输入为5,其二进制为101,输出应为

1
3

下面是我的代码,它只提供输出2而不是我想提供一个二进制表示的位置。我怎样才能从1开始设置位的位置?

public static void main(String args[]) throws Exception {
    System.out.println(countBits(5));
}

private static int countBits(int number) {
    boolean flag = false;

    if (number < 0) {
        flag = true;
        number = ~number;
    }
    int result = 0;
    while (number != 0) {
        result += number & 1;
        number = number >> 1;
    }
    return flag ? (32 - result) : result;
}

5 个答案:

答案 0 :(得分:9)

countBits返回结果而不是在方法中放置System.out.println的想法通常是最好的方法。如果你想让它返回一个位位置列表,那么模拟就是让你的方法返回一个数组或某种List,如:

private static List<Integer> bitPositions(int number) {

正如我在评论中提到的,如果您使用>>>并删除特殊代码以检查否定,您将使自己的生活更轻松。这样做,并调整你已经拥有的代码,给你一些像

private static List<Integer> bitPositions(int number) {
    List<Integer> positions = new ArrayList<>();
    int position = 1;
    while (number != 0) {
        if (number & 1 != 0) {
            positions.add(position);
        }
        position++;
        number = number >>> 1;
    }
    return positions;
}

现在,来电者可以按照自己的意愿打印出来。如果您使用System.out.println,则输出将为[1, 3]。如果您希望每个输出单独一行:

for (Integer position : bitPositions(5)) {
     System.out.println(position);
}

在任何情况下,关于如何打印位置(或任何你想用它们做的事情)的决定都与计算位置的逻辑分开,因为该方法返回整个列表并且没有有自己的println

(顺便说一句,正如亚历克斯所说,将低阶位视为&#34;位0和#34;而不是&#34;位1&#34;最常见,尽管我已经看到硬件手册调用低位#34位#34;高位位&#34;位0&#34;。调用它的优势&#34;位0&#34;是位置N的1位代表值2 N ,简单易行。我的代码示例将其称为&#34;位1和#34;正如您在问题中所要求的那样;但如果要将其更改为0,只需更改position的初始值。)

答案 1 :(得分:3)

您需要跟踪自己所处的位置,并在number & 1结果为1时打印出该位置。它看起来像:

...
int position = 1;
while (number != 0) {
    if((number & 1)==1)
        System.out.println(position);
    result += number & 1;
    position += 1;
    number = number >> 1;
}
...

答案 2 :(得分:3)

二进制表示:您的数字与现代(非量子)计算机上的任何内容一样,已经是内存中的二进制表示形式,作为给定大小的位序列。

位操作 您可以使用位移,位掩码,“AND”,“OR”,“NOT”和“XOR”bitwise operations来操纵它们,并在各个位的级别上获取有关它们的信息。

您的示例

对于您的示例数字5(101),您提到您的预期输出为1, 3。这有点奇怪,因为一般来说,一个人会从0开始计数,例如5为byte(8位数):

     76543210  <-- bit index
5    00000101

所以我希望输出为02,因为这些位索引的位已设置(1)。

您的示例实现显示了函数的代码

private static int countBits(int number)

它的名称和签名意味着任何实现的以下行为:

  • 它需要一个整数值number并返回一个输出值。
  • 用于计算输入number中设置的位数。

即。它与您描述的预期功能完全不匹配。

解决方案

您可以结合使用“位移”(>>)和AND&)操作来解决问题。

int index = 0; // start at bit index 0

while (inputNumber != 0) { // If the number is 0, no bits are set

    // check if the bit at the current index 0 is set
    if ((inputNumber & 1) == 1)         
        System.out.println(index);  // it is, print its bit index.

    // advance to the next bit position to check
    inputNumber = inputNumber >> 1; // shift all bits one position to the right
    index = index + 1;              // so we are now looking at the next index.
}

如果我们为您的示例输入数字'5'运行此操作,我们将看到以下内容:

iteration   input  76543210     index    result
1           5      00000101     0        1 => bit set.
2           2      00000010     1        0 => bit not set.
3           1      00000001     2        1 => bit set.
4           0      00000000     3        Stop, because inputNumber is 0    

答案 3 :(得分:1)

有一种方法可以使用逐位操作来解决您的问题 Integer.toBinaryString(int number)将整数转换为由0和1组成的String。这在你的情况下很方便,因为你可以改为:

public static void main(String args[]) throws Exception {
    countBits(5);
}

public static void countBits(int x) {
  String binaryStr = Integer.toBinaryString(x);
  int length = binaryStr.length();
  for(int i=0; i<length; i++) {
    if(binaryStr.charAt(i)=='1')
      System.out.println(length-1);
  }
}

它绕过了你可能想要做的事情(在Java中学习按位操作),但在我看来使代码看起来更干净。

答案 4 :(得分:0)

Integer.lowestOneBit和Integer.numberOfTrailingZeros的组合立即给出最低1位的位置,如果数字为0则返回32。

因此,以下代码以升序返回数字 number 的1位位置:

public static List<Integer> BitOccurencesAscending(int number)
{
    LinkedList<Integer> out = new LinkedList<>();
    int x = number;
    while(number>0)
    {
        x = Integer.lowestOneBit(number);
        number -= x;
        x = Integer.numberOfTrailingZeros(x);
        out.add(x);
    }
    return out;
}