按位否定会产生意外结果

Jos*_*bel 7 java bit-manipulation

我试图在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));
    }
}
Run Code Online (Sandbox Code Playgroud)

它输出-110为什么?

Edw*_*uck 11

你假设101是三位长.Java不支持可变长度位操作,它在整个int位上操作,因此~将是not32位长"101".

---被问到"我怎么能解决这个问题后编辑?" ---

这是一个非常好的问题,但答案是"你不能"和"你可以通过不同方式实现同​​样的事情".

您无法修复~运算符,因为它执行的操作.这有点像要求修复+只添加1的位置.只是不会发生.

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

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

 int masked_inverse = (~value) & mask;
Run Code Online (Sandbox Code Playgroud)

注意,我们所做的实际上是反转32位,然后将这些位中的29位归零; 因为,它们在面具中被设置为零,这意味着"我们不关心它们".这也可以想象为利用&运营商,我们说"如果设置,我们关心它,设置它".

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

幸运的是,有人已经这样做了.它是标准Java库的一部分,称为aBitSet.

BitSet threeBits = new BitSet(3);
threeBits.set(2);  // set bit index 2
threeBits.set(0);  // set bit index 0
threeBits.flip(0,3);
Run Code Online (Sandbox Code Playgroud)

然而,由于Java中类/对象系统的约束,这种位操作对它们有不同的感觉,这是因为将类定义为在Java中添加新类型的唯一方法.