按位否定给人意想不到的结果(Bitwise negation gives unexpected re

2019-07-22 17:17发布

我试图用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为什么呢?

Answer 1:

你是假设101是3位长。 Java不支持可变长度的位操作,在整个操作int位的,所以~将是not的一个32位长的“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中添加新类型的必由之路随后的制约。



Answer 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


Answer 3:

101整数实际上表示为00000000000000000000000000000101否定这一点,你会得到11111111111111111111111111111010 -这是-6



Answer 4:

的toString()方法解释其作为带符号的值的参数。

为了证明二进制运算它能够更好地使用Integer.toBinaryString() 它解释其参数为无符号,所以〜101输出为11111111111111111111111111111010。

如果你想输出的较少比特可以屏蔽与和结果。



Answer 5:

只是对埃德温的回答详细一点 - 如果你正在寻找创建一个可变长度的面具开发感兴趣的位,你可能需要一些辅助功能:

/**
 * 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);
}


文章来源: Bitwise negation gives unexpected result