java java位操作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/563544/
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-29 12:52:22  来源:igfitidea点击:

java bit manipulation

javabit-manipulationbyte

提问by jbu

byte x = -1;
for(int i = 0; i < 8; i++)
{
    x = (byte) (x >>> 1);
    System.out.println("X: " + x);
}

As I understand it, java stores data in two's-complement, meaning -1 = 11111111 (according to wikipedia).

据我了解,java 以二进制补码形式存储数据,这意味着 -1 = 11111111(根据维基百科)。

Also, from the java docs: "The bit pattern is given by the left-hand operand, and the number of positions to shift by the right-hand operand. The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension. "

此外,来自 java 文档:“位模式由左侧操作数和右侧操作数移位的位置数给出。无符号右移运算符“>>>”将零移到最左侧位置,而“>>”后最左边的位置取决于符号扩展。”

Which means that >>> would shift a 0 to the left most bit every time. So I expect this code to be

这意味着 >>> 每次都会将 0 移到最左边的位。所以我希望这段代码是

iteration: bit representation of x

迭代:x 的位表示

0: 11111111

0: 11111111

1: 01111111

1:01111111

2: 00111111

2:00111111

3: 00011111

3:00011111

...so on

...很快

However, my output is always X: -1, meaning (I guess) that >>> is putting the sign bit in the left most position. So I then try >>, and same result.

但是,我的输出始终是 X: -1,这意味着(我猜)是 >>> 将符号位放在最左边的位置。所以我然后尝试>>,和相同的结果。

What's going on? I would expect my output to be: X: -1, x: 127, x: 63, etc.

这是怎么回事?我希望我的输出是:X:-1、x:127、x:63 等。

回答by paxdiablo

Whoever thought that bytes should be signed when Java was invented should be taken out and beaten with a wet stick of celery until they cry :-)

谁认为在 Java 发明时应该对字节进行签名,应该取出并用湿芹菜棒殴打直到他们哭:-)

You can do what you want by casting up to an int and ensuring you never shift a 1 into the top bit, something like this:

您可以通过强制转换为 int 并确保永远不会将 1 移到最高位来做您想做的事情,如下所示:

byte x = -1;
int x2 = ((int)x) & 0xff;
for(int i = 0; i < 8; i++)
{
    x2 = (x2 >>> 1);
    System.out.println("X: " + x2);
}

Your particular problem is because >>> is casting up to an int to do the shift, then you're casting it back to a byte, as shown here:

您的特殊问题是因为 >>> 正在转换为 int 来进行转换,然后您将其转换回一个字节,如下所示:

byte x = -1;
int x2 = ((int)x) & 0xff;
int x3;
int x4 = x2;
for(int i = 0; i < 8; i++)
{
    x2 = (x2 >>> 1);
    System.out.println("X2: " + x2);
    x3 = (x >>> 1);
    x = (byte)x3;
    x4 = (x4 >>> 1);
    System.out.println("X: " + x3 + " " + x + " " + x4);
}

Which outputs:

哪些输出:

X2: 127
X: 2147483647 -1 127
X2: 63
X: 2147483647 -1 63
X2: 31
X: 2147483647 -1 31
X2: 15
X: 2147483647 -1 15
X2: 7
X: 2147483647 -1 7
X2: 3
X: 2147483647 -1 3
X2: 1
X: 2147483647 -1 1
X2: 0
X: 2147483647 -1 0

You can clearly see that x and x3 don't work (even though x3 shifts correctly, casting it back to byte in x sets it to -1 again). x4 works perfectly.

您可以清楚地看到 x 和 x3 不起作用(即使 x3 正确移位,将其转换回 x 中的字节又将其设置为 -1)。x4 完美运行。

回答by Neil Coffey

Remember that:

请记住:

  • operands of bitwise operationsare always promoted to at least an int!
  • casts always involve sign extension.
  • 按位运算的操作数总是至少提升为 int
  • 强制转换总是涉及符号扩展

So when you do (x >>> n), even though you defined x as a byte, for the purposes of the shift, it will be first converted to an int. If the byte being converted is negative, then all of the "extra bits" (so, the leftmost 24 bits of the resulting int) added to make it up to an int will be set to 1. Or put another way, if the original byte was -1, the thing you're actually shifting is -1 as an int, i.e. 32-bit number with all 32 bits set to 1. Shifting this right by 1-8 places will still result in the bottom 8 bits all set to 1, hence when you cast back to a byte, you end up with a byte with all 8 bits set to 1, or in other words, a byte value of -1.

因此,当您执行 (x >>> n) 时,即使您将 x 定义为字节,但出于移位的目的,它也会首先转换为 int。如果被转换的字节是负数,那么所有添加到 int 中的“额外位”(因此,结果 int 的最左边的 24 位)将被设置为 1。或者换句话说,如果原始byte 是 -1,你实际移动的东西是 -1 作为int,即所有 32 位都设置为 1 的 32 位数字。将这个右移 1-8 位仍然会导致底部 8 位全部设置到 1,因此当你转换回一个字节时,你最终得到一个所有 8 位都设置为 1 的字节,或者换句话说,一个字节值为 -1。

回答by Himadri Choudhury

I'm not sure about this. But, my guess is that

我不确定这一点。但是,我的猜测是

x >>> 1 

gets promoted to a int from byte, because the literal "1" is an int. Then what you are observing makes sense.

从字节被提升为 int,因为文字“1”是一个 int。那么你所观察到的就有意义了。

回答by Jacob Krall

I don't know why it doesn't work, but an easy way to clear the top bit is to & with (binary) 0111111:

我不知道为什么它不起作用,但是清除最高位的一种简单方法是使用(二进制)0111111 & :

x = (byte) (x >>> 1) & 0x7F;

回答by user85421

The problem is, as told before (long time ago), that x get upcasted to int (sign-extended) before doing the shift.
Doing a "bit-to-bit" conversion should help:

问题是,如前所述(很久以前),在进行转换之前,x 被向上转换为 int(符号扩展)。
进行“位到位”转换应该会有所帮助:

byte x = -1;
for(int i = 0; i < 8; i++)
{
    x = (byte) ((x & 0xFF) >>> 1);
    System.out.println("X: " + x);
}