问题描述
我在使用 0xff 执行 AND 运算符时遇到问题。
public Pixel(int x,int y,int p) {
this.x = x;
this.y = y;
pixelValue = p;
A = (byte) ((p>>24) & 0xff);
R = (byte) ((p>>16) & 0xff);
R = (byte) (R&0xff);
G = (byte) ((p>>8) & 0xff);
B =(byte) (p & 0xff);
printAll();
}
void printAll() {
System.out.println("A "+Integer.toBinaryString(A));
System.out.println(Byte.toUnsignedInt(A));
System.out.println("R "+Integer.toBinaryString(R));
System.out.println(Byte.toUnsignedInt(R));
System.out.println("G "+Integer.toBinaryString(G));
System.out.println(Byte.toUnsignedInt(G));
System.out.println("B "+Integer.toBinaryString(B));
System.out.println(Byte.toUnsignedInt(B));
System.out.println("pixelValue"+pixelValue);
System.out.println(Integer.toBinaryString((byte)(pixelValue)));
}
在执行 Pixel p = new Pixel(0,2145687240);
时
我得到
A 1111111
127
R 11111111111111111111111111100100
228
G 11111111111111111111111110010110
150
B 11111111111111111111111111001000
200
pixelValue-56
11111111111111111111111111001000
问题是,为什么 R、G 和 B 都填充了 1?为什么A只有7位? 为什么在调用 &0xff 时我得到 11111111111111111111111111100100?这不应该取消前 8 个字节以外的所有内容吗?
解决方法
字节从 0
到 255
(含),因为它们可以容纳 2^8=256
值。至少那是未签名的定义。
这里要问自己的问题是:如何表示负数?典型的方法是使用称为二进制补码的东西。第一位,不是像通常那样在关闭时表示 0
和在打开时表示 2^(n-1)
,而是在关闭时表示 0
和打开时表示 -2^(n-1)
。
因此,228
在内部存储为 11100100
。如果您将其从基数 2 转换,您将看到这等于 228
... 但仅当未签名时。
签名后,最后 7 位代表 100
。然后,第一位,而不是代表128
,而是代表-128
。因此,签名时值为 -28
。
那么,当把它转换成整数时,由于一个整数有32位,那么第一位将表示-2147483648
,因此最后31位将需要表示28 + 2147483648
,即1111111111111111111111111100100
来自。因此,-28
的 32 位表示是 11111111111111111111111111100100
。
如果您真的想拥有 228
,您可能希望对 Integer.toBinaryString
的结果调用 Byte.toUnsignedInt
,顾名思义,它会将其转换为 无符号 号码。这里的问题是它正在签名,这意味着它是-28
,而不是您想要的228
。