7

我正在尝试用 java 编写一个按位计算器,您可以输入一个表达式,例如 ~101,它会返回 10 但是当我运行此代码时

import java.util.Scanner;

public class Test
{
    public static void main(String[] args)
    {
        Integer a = Integer.valueOf("101", 2);
        System.out.println(Integer.toString(~a,2));
    }
}

它输出-110 为什么?

4

5 回答 5

11

您假设 101 是三位长。Java 不支持可变长度位操作,它对整个int位进行操作,因此~将是not32 位长的“101”。

--- 在被问到“我该如何解决这个问题?”后编辑。---

这是一个非常好的问题,但答案是“你不能”和“你可以通过不同的方式实现同​​样的事情”的混合体。

您无法修复~操作员,因为它会做它所做的事情。这有点像要求修复+只添加 1 的位置。只是不会发生。

您可以实现所需的操作,但您需要更多的“东西”来实现它。首先,您必须有一些东西(另一个 int)来指定感兴趣的位。这通常称为位掩码

 int mask = 0x00000007; // just the last 3 bits.

 int masked_inverse = (~value) & mask;

请注意,我们所做的实际上是反转 32 位,然后将其中的 29 位归零;因为,它们在掩码中被设置为零,这意味着“我们不关心它们”。这也可以想象为利用&运营商,例如我们说“如果设置并且我们关心它,请设置它”。

现在你仍然有 32 位,但只有低 3 位会被反转。如果你想要一个 3 位数据结构,那就另当别论了。Java(和大多数语言)只是不直接支持这些东西。因此,您可能很想向 Java 添加另一种类型来支持它。Java 通过机制添加类型,但内置类型是不可更改的。这意味着您可以编写一个类来表示一个 3 位数据结构,但它必须在内部将整数处理为 32 位字段。

对你来说幸运的是,已经有人这样做了。它是标准 Java 库的一部分,称为BitSet.

BitSet threeBits = new BitSet(3);
threeBits.set(2);  // set bit index 2
threeBits.set(0);  // set bit index 0
threeBits.flip(0,3);

但是,由于 Java 中的类/对象系统的限制,这种位操作对他们有不同的感觉,这源于将类定义为在 Java 中添加新类型的唯一方法。

于 2013-03-22T16:48:45.130 回答
2

如果a = ...0000101 (bin) = 5 (dec)

~a = ~...0000101(bin) = ...1111010(bin) 

而Java使用“二进制补码”形式来表示负数,所以

~a = -6 (dec)

Integer.toBinaryString(number)现在和Integer.toString(number, 2)负数的区别在于

  • toBinaryString以“二进制补码”形式返回字符串,但
  • toString(number, 2)计算二进制形式,如果数字是正数,如果参数是负数,则添加“减号”标记。

所以toString(number, 2)为了~a = -6意志

  1. 计算6->的二进制值0000110
  2. 修剪前导零 -> 110,
  3. 添加减号 -> -110
于 2013-03-22T17:24:31.640 回答
0

toString() 方法将其参数解释为有符号值。

为了演示二进制操作,最好使用Integer.toBinaryString(). 它将其参数解释为无符号,因此 ~101 输出为 1111111111111111111111111111010。

如果你想要更少的输出位,你可以用 & 屏蔽结果。

于 2013-03-22T16:46:19.793 回答
0

整数 101 实际上表示为00000000000000000000000000000101否定 this 并且你得到11111111111111111111111111111010- 这是-6.

于 2013-03-22T16:46:58.647 回答
0

只是为了详细说明 Edwin 的答案 - 如果您想创建一个可变长度掩码来开发感兴趣的位,您可能需要一些辅助函数:

/**
 * Negate a number, specifying the bits of interest.
 * 
 * Negating 52 with an interest of 6 would result in 11 (from 110100 to 001011).
 * Negating 0 with an interest of 32 would result in -1 (equivalent to ~0).
 * 
 * @param number the number to negate.
 * @param bitsOfInterest the bits we're interested in limiting ourself to (32 maximum).
 * @return the negated number.
 */
public int negate(int number, int bitsOfInterest) {
    int negated = ~number;
    int mask = ~0 >>> (32 - bitsOfInterest);
    logger.info("Mask for negation is [" + Integer.toBinaryString(mask) + "]");
    return negated & mask;
}

/**
 * Negate a number, assuming we're interesting in negation of all 31 bits (exluding the sign).
 * 
 * Negating 32 in this case would result in ({@link Integer#MAX_VALUE} - 32).
 * 
 * @param number the number to negate.
 * @return the negated number.
 */
public int negate(int number) {
    return negate(number, 31);
}
于 2014-04-18T02:21:14.787 回答