Java移位陌生 [英] Java bitshift strangeness

查看:152
本文介绍了Java移位陌生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java具有2位移位操作符,用于右移:

Java has 2 bitshift operators for right shifts:

>> shifts right, and is dependant on the sign bit for the sign of the result

>>> shifts right and shifts a zero into leftmost bits

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html

这似乎很简单,所以任何人都可以向我解释为什么这个代码,当给出一个值为-128的bar时,为foo生成一个值-2:

This seems fairly simple, so can anyone explain to me why this code, when given a value of -128 for bar, produces a value of -2 for foo:

byte foo = (byte)((bar & ((byte)-64)) >>> 6);

这是要做一个8位字节,最左边2位的掩码,他们进入最右边的2位。即:

What this is meant to do is take an 8bit byte, mask of the leftmost 2 bits, and shift them into the rightmost 2 bits. Ie:

initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b10000000
0b10000000 >>> 6 = 0b00000010

结果实际上是-2,这是

The result actually is -2, which is

0b11111110

1而不是零转移到左侧位置

Ie. 1s rather than zeros are shifted into left positions

推荐答案

这是因为&实际上正在执行升级到 int - 这留下了很多1位。然后你正在向右移动,最左边的2位为0,然后忽略那些最左边的位被转回到字节。

It's because the & is actually performing promotion to int - which leaves an awful lot of "1" bits. You're then shifting right, leaving the leftmost 2 bits as 0, but then ignoring those leftmost bits by casting back to byte.

当你分离出操作:

public class Test
{
    public static void main(String[] args)
    {
        byte bar = -128;
        int tmp = (bar & ((byte)-64)) >>> 6;
        byte foo = (byte)tmp;
        System.out.println(tmp);
        System.out.println(foo);
    }
}

打印

67108862
-2

所以要再次进行一点算术:

So to do your bit arithmetic again:

initial = 0b10000000 (-128)
-64 = 0b11000000
initial & -64 = 0b11111111111111111111111110000000 // it's an int now
0b10000000 >>> 6 = 0b00111111111111111111111111100000 // note zero-padding
(byte) (0b10000000 >>> 6) = 11100000 // -2

即使你得到正确的结果,操作(通过此时的转换),>>> 将首先将第一个操作数提升到 int

Even if you get the right result out of the & operation (by casting at that point), >>> will promote the first operand to int first anyway.

编辑:解决方案是改变你如何掩饰事物。而不是屏蔽-64,掩码只是128 + 64 = 192 = 0xc0代替:

The solution is to change how you mask things. Instead of masking by -64, mask by just 128+64=192=0xc0 instead:

byte foo = (byte)((bar & 0xc0) >>> 6);

这样,你真的只需要两位你想要的,而不是加载1s在最重要的24位。

That way you really only get left with the two bits you want, instead of having a load of 1s in the most significant 24 bits.

这篇关于Java移位陌生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆