我正在尝试在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为什么?
答案 0 :(得分:11)
您假设101是三位长。 Java不支持可变长度位操作,它在整个int
位上运行,因此~
将是32位长“101”的not
。
---被问到“如何解决这个问题?”后编辑。 ---
这是一个非常好的问题,但答案是“你不能”和“你可以通过不同方式达到同样的目标”的混合。
您无法修复~
运算符,因为它执行的操作。这有点像要求修复+
只添加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库的一部分,is called a 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中添加新类型。
答案 1 :(得分:2)
如果a = ...0000101 (bin) = 5 (dec)
~a = ~...0000101(bin) = ...1111010(bin)
和Java使用“Two's complement”表单来表示负数,所以
~a = -6 (dec)
现在Integer.toBinaryString(number)
和Integer.toString(number, 2)
之间的负数差异是
toBinaryString
以“Two's complement”形式返回字符串,但toString(number, 2)
计算二进制形式,如果数字为正数,如果参数为负数,则添加“减号”标记。 因此toString(number, 2)
~a = -6
将
6
的二进制值 - > 0000110
,110
,-110
。答案 2 :(得分:0)
toString()方法将其参数解释为有符号值。
为了演示二进制操作,最好使用Integer.toBinaryString()
。它将其参数解释为无符号,因此~101输出为1111111111111111111111111111111010。
如果您想要更少的输出位,可以使用&。
屏蔽结果答案 3 :(得分:0)
整数101实际上表示为00000000000000000000000000000101
否定此项,您得到11111111111111111111111111111010
- 这是-6
。
答案 4 :(得分: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);
}