Java - &0xff 给出从 8 到 31 的位为 1
Java - &0xff gives bits from 8 to 31 as 1's
我在使用 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,0,2145687240);
我得到
A 1111111
127
R 11111111111111111111111111100100
228
G 11111111111111111111111110010110
150
B 11111111111111111111111111001000
200
pixelValue-56
11111111111111111111111111001000
问题来了,为什么R、G、B全是1?为什么 A 只有 7 位?
为什么在调用 &0xff 时我得到 111111111111111111111111100100?这不应该取消除前 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
,您可能希望对 Byte.toUnsignedInt
的结果调用 Integer.toBinaryString
,顾名思义,它会将其转换为无符号 数。这里的问题是它被签名,这意味着它是-28
,而不是你想要的228
。
我在使用 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,0,2145687240);
我得到
A 1111111
127
R 11111111111111111111111111100100
228
G 11111111111111111111111110010110
150
B 11111111111111111111111111001000
200
pixelValue-56
11111111111111111111111111001000
问题来了,为什么R、G、B全是1?为什么 A 只有 7 位? 为什么在调用 &0xff 时我得到 111111111111111111111111100100?这不应该取消除前 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
,您可能希望对 Byte.toUnsignedInt
的结果调用 Integer.toBinaryString
,顾名思义,它会将其转换为无符号 数。这里的问题是它被签名,这意味着它是-28
,而不是你想要的228
。