java 按位否定给出了意想不到的结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15575520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:07:18  来源:igfitidea点击:

Bitwise negation gives unexpected result

javabit-manipulation

提问by Josh Sobel

I am trying to write a bitwise calculator in java, something that you could input an expression such as ~101 and it would give back 10 however when i run this code

我正在尝试用 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));
    }
}

it outputs -110 why?

它输出-110 为什么?

回答by Edwin Buck

You are assuming that 101 is three bits long. Java doesn't support variable length bit operations, it operates on a whole intof bits, so ~will be the notof a 32 bit long "101".

您假设 101 是三位长。Java不支持可变长度的位操作,在整个操作int的位,所以~将是not一个32位长的“101”。

--- Edited after being asked "How can I fix this?" ---

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

That's a really good question, but the answer is a mix of "you can't" and "you can achieve the same thing by different means".

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

You can't fix the ~operator, as it does what it does. It would sort of be like asking to fix +to only add the 1's place. Just not going to happen.

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

You can achieve the desired operation, but you need a bit more "stuff" to get it going. First you must have something(another int) that specifies the bits of interest. This is typically called a bit mask.

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

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

 int masked_inverse = (~value) & mask;

Note that what we did was really invert 32 bits, then zeroed out 29 of those bits; because, they were set to zero in the mask, which means "we don't care about them". This can also be imagined as leveraging the &operator such that we say "if set and we care about it, set it".

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

Now you will stillhave 32 bits, but only the lower 3 will be inverted. If you want a 3 bit data structure, then that's a different story. Java (and most languages) just don't support such things directly. So, you might be tempted to add another typeto Java to support that. Java adds types via a classmechanism, but the built-in types are not changeable. This means you could write a class to represent a 3 bit data structure, but it will have to handle ints internally as 32 bit fields.

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

Fortunately for you, someone has already done this. It is part of the standard Java library, and is called a BitSet.

幸运的是,有人已经这样做了。它是标准 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);

However, such bit manipulations have a different feel to them due to the constraints of the Class / Object system in Java, which follows from defining classes as the only wayto add new types in Java.

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

回答by Pshemo

If a = ...0000101 (bin) = 5 (dec)

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

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

and Java uses "Two's complement" form to represent negative numbers so

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

~a = -6 (dec)

Now difference between Integer.toBinaryString(number)and Integer.toString(number, 2)for negative number is that

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

  • toBinaryStringreturns String in "Two's complement" form but
  • toString(number, 2)calculates binary form as if number was positive and add "minus" mark if argument was negative.
  • toBinaryString以“二进制补码”形式返回字符串,但
  • toString(number, 2)计算二进制形式,就好像数字是正数一样,如果参数是负数,则添加“减号”标记。

So toString(number, 2)for ~a = -6will

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

  1. calculate binary value for 6-> 0000110,
  2. trim leading zeros -> 110,
  3. add minus mark -> -110.
  1. 计算二进制值6-> 0000110
  2. 修剪前导零 -> 110,
  3. 添加减号 -> -110

回答by David Levy

Just to elaborate on Edwin's answer a bit - if you're looking to create a variable length mask to develop the bits of interest, you might want some helper functions:

只是为了详细说明 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);
}

回答by Joni

The toString() method interprets its argument as a signed value.

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

To demonstrate binary operations its better to use Integer.toBinaryString(). It interprets its argument as unsigned, so that ~101 is output as 11111111111111111111111111111010.

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

If you want fewer bits of output you can mask the result with &.

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

回答by enigma

101 in integer is actually represented as 00000000000000000000000000000101negate this and you get 11111111111111111111111111111010- this is -6.

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