Java 将 int 转换为 byte 时的奇怪行为?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/842817/
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
Odd behavior when Java converts int to byte?
提问by harshit
int i =132;
byte b =(byte)i; System.out.println(b);
Mindboggling. Why is the output -124
?
令人难以置信。为什么是输出-124
?
采纳答案by Wayne
In Java, an int
is 32 bits. A byte
is 8 bits
.
在 Java 中,anint
是 32 位。Abyte
是 8 bits
。
Most primitive types in Java are signed, and byte
, short
, int
, and long
are encoded in two's complement. (The char
type is unsigned, and the concept of a sign is not applicable to boolean
.)
最原始的类型Java中的签名,byte
,short
,int
,和long
被编码在二进制补码。(char
类型是无符号的,符号的概念不适用于boolean
。)
In this number scheme the most significant bit specifies the sign of the number. If more bits are needed, the most significant bit ("MSB") is simply copied to the new MSB.
在此数字方案中,最高有效位指定数字的符号。如果需要更多位,则将最高有效位(“MSB”)简单地复制到新的 MSB。
So if you have byte 255
: 11111111
and you want to represent it as an int
(32 bits) you simply copy the 1 to the left 24 times.
因此,如果您有 byte 255
:11111111
并且您想将其表示为int
(32 位),您只需将 1 向左复制 24 次。
Now, one way to read a negative two's complement number is to start with the least significant bit, move left until you find the first 1, then invert every bit afterwards. The resulting number is the positive version of that number
现在,读取负二进制补码数的一种方法是从最低有效位开始,向左移动直到找到第一个 1,然后反转每一位。结果数字是该数字的正数
For example: 11111111
goes to 00000001
= -1
. This is what Java will display as the value.
例如:11111111
转到00000001
= -1
。这是 Java 将显示为值的内容。
What you probably want to do is know the unsigned value of the byte.
您可能想要做的是知道字节的无符号值。
You can accomplish this with a bitmask that deletes everything but the least significant 8 bits. (0xff)
您可以使用位掩码来完成此操作,该位掩码会删除除最低有效 8 位之外的所有内容。(0xff)
So:
所以:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
Would print out: "Signed: -1 Unsigned: 255"
会打印出来: "Signed: -1 Unsigned: 255"
What's actually happening here?
这里究竟发生了什么?
We are using bitwise AND to mask all of the extraneous sign bits (the 1's to the left of the least significant 8 bits.) When an int is converted into a byte, Java chops-off the left-most 24 bits
我们使用按位 AND 来屏蔽所有无关的符号位(最低有效 8 位左侧的 1)。当 int 转换为字节时,Java 会砍掉最左侧的 24 位
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Since the 32nd bit is now the sign bit instead of the 8th bit (and we set the sign bit to 0 which is positive), the original 8 bits from the byte are read by Java as a positive value.
由于第 32 位现在是符号位而不是第 8 位(并且我们将符号位设置为 0,这是正数),因此 Java 将字节中的原始 8 位读取为正值。
回答by bdonlan
byte in Java is signed, so it has a range -2^7 to 2^7-1 - ie, -128 to 127. Since 132 is above 127, you end up wrapping around to 132-256=-124. That is, essentially 256 (2^8) is added or subtracted until it falls into range.
Java 中的字节是有符号的,所以它的范围是 -2^7 到 2^7-1 - 即 -128 到 127。由于 132 大于 127,你最终会环绕到 132-256=-124。也就是说,本质上增加或减去 256 (2^8) 次,直到它落入范围内。
For more information, you may want to read up on two's complement.
有关更多信息,您可能需要阅读二进制补码。
回答by Peter Lawrey
132 is outside the range of a byte which is -128 to 127 (Byte.MIN_VALUE to Byte.MAX_VALUE) Instead the top bit of the 8-bit value is treated as the signed which indicates it is negative in this case. So the number is 132 - 256 = -124.
132 超出了 -128 到 127(Byte.MIN_VALUE 到 Byte.MAX_VALUE)的字节范围,而是将 8 位值的最高位视为有符号的,这表示在这种情况下它是负数。所以数字是 132 - 256 = -124。
回答by Pacerier
132
in digits (base 10) is 1000_0100
in bits (base 2) and Java stores int
in 32 bits:
132
在数字(基数 10)是1000_0100
在位(基数 2)和 Java 存储int
在 32 位:
0000_0000_0000_0000_0000_0000_1000_0100
Algorithm for int-to-byte is left-truncate; Algorithm for System.out.println
is two's-complement(Two's-complement is if leftmost bit is 1
, interpret as negative one's-complement(invert bits) minus-one.); Thus System.out.println(int-to-byte(
))
is:
int-to-byte 的算法是左截断的;算法 for System.out.println
is two's -complement(Two's-complement is if most left bit is 1
,解释为负的补码(反转位)减一。); 因此System.out.println(int-to-byte(
))
是:
- interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(] left-truncate(
0000_0000_0000_0000_0000_0000_1000_0100
) [)))] ) - =interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(]
1000_0100
[)))] ) - =interpret-as(negative(invert-bits(minus-one(
1000_0100
)))) - =interpret-as(negative(invert-bits(
1000_0011
))) - =interpret-as(negative(
0111_1100
)) - =interpret-as(negative(124))
- =interpret-as(-124)
- =-124 Tada!!!
- 解释为(if-leftmost-bit-is-1[negative(invert-bits(minus-one(] left-truncate(
0000_0000_0000_0000_0000_0000_1000_0100
) [)))]] - = 解释为(如果最左位是 1[ 负(反转位(减一(]
1000_0100
[)))] ) - =解释为(负(反转位(减一(
1000_0100
)))) - =解释为(负(反转位(
1000_0011
))) - =解释为(否定(
0111_1100
)) - =解释为(否定(124))
- =解释为(-124)
- =-124多田!!!
回答by pen
often in books you will find the explanation of casting from int to byte as being performed by modulus division. this is not strictly correct as shown below what actually happens is the 24 most significant bits from the binary value of the int number are discarded leaving confusion if the remaining leftmost bit is set which designates the number as negative
通常在书中,您会发现从 int 转换为 byte 的解释是由模数除法执行的。这并不严格正确,如下所示,实际发生的情况是 int 数字的二进制值中的 24 个最高有效位被丢弃,如果剩余的最左边的位被设置为负数,则会留下混淆
public class castingsample{
public static void main(String args[]){
int i;
byte y;
i = 1024;
for(i = 1024; i > 0; i-- ){
y = (byte)i;
System.out.print(i + " mod 128 = " + i%128 + " also ");
System.out.println(i + " cast to byte " + " = " + y);
}
}
}
回答by typelogic
here is a very mechanical method without the distracting theories:
这是一个非常机械的方法,没有分散注意力的理论:
- Convert the number into binary representation (use a calculator ok?)
- Only copy the rightmost 8 bits (LSB) and discard the rest.
- From the result of step#2, if the leftmost bit is 0, then use a calculator to convert the number to decimal. This is your answer.
- Else (if the leftmost bit is 1) your answer is negative. Leave all rightmost zeros and the first non-zero bit unchanged. And reversed the rest, that is, replace 1's by 0's and 0's by 1's. Then use a calculator to convert to decimal and append a negative sign to indicate the value is negative.
- 将数字转换为二进制表示(使用计算器好吗?)
- 只复制最右边的 8 位 (LSB) 并丢弃其余的。
- 从步骤#2 的结果来看,如果最左边的位是 0,则使用计算器将数字转换为十进制。这是你的答案。
- 否则(如果最左边的位是 1)你的答案是否定的。保留所有最右边的零和第一个非零位不变。并将其余的颠倒过来,即用0代替1,用1代替0。然后使用计算器转换为十进制并附加一个负号表示该值为负数。
This more practical method is in accordance to the much theoretical answers above. So, those still reading those Java books saying to use modulo, this is definitely wrong since the 4 steps I outlined above is definitely not a modulo operation.
这种更实用的方法与上面的许多理论答案一致。所以,那些仍在阅读那些说要使用模的 Java 书籍的人,这绝对是错误的,因为我上面概述的 4 个步骤绝对不是模运算。
回答by bcorso
In Java, byte
(N=8) and int
(N=32) are represented by the 2s-complement shown above.
在 Java 中,byte
(N=8) 和int
(N=32) 由上面显示的 2s 补码表示。
From the equation, a7is negative for byte
but positive for int
.
从等式中,a 7 对为负byte
但对 为正int
。
coef: a7 a6 a5 a4 a3 a2 a1 a0
Binary: 1 0 0 0 0 1 0 0
----------------------------------------------
int: 128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = 132
byte: -128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = -124
回答by Francisco Neto
A quick algorithm that simulates the way that it work is the following:
模拟其工作方式的快速算法如下:
public int toByte(int number) {
int tmp = number & 0xff
return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}
How this work ? Look to daixtranswer. A implementation of exact algorithm discribed in his answer is the following:
这是如何工作的?看看daixtr 的回答。他的回答中描述的精确算法的实现如下:
public static int toByte(int number) {
int tmp = number & 0xff;
if ((tmp & 0x80) == 0x80) {
int bit = 1;
int mask = 0;
for(;;) {
mask |= bit;
if ((tmp & bit) == 0) {
bit <<=1;
continue;
}
int left = tmp & (~mask);
int right = tmp & mask;
left = ~left;
left &= (~mask);
tmp = left | right;
tmp = -(tmp & 0xff);
break;
}
}
return tmp;
}
回答by devil_29
N is input number
case 1: 0<=N<=127 answer=N;
case 2: 128<=N<=256 answer=N-256
case 3: N>256
temp1=N/256;
temp2=N-temp*256;
if temp2<=127 then answer=temp2;
else if temp2>=128 then answer=temp2-256;
case 4: negative number input
do same procedure.just change the sign of the solution
回答by Bathsheba
Conceptually, repeated subtractions of 256 are made to your number, until it is in the range -128 to +127. So in your case, you start with 132, then end up with -124 in one step.
从概念上讲,对您的数字进行 256 的重复减法,直到它在 -128 到 +127 的范围内。因此,在您的情况下,您从 132 开始,然后一步以 -124 结束。
Computationally, this corresponds to extracting the 8 least significant bits from your original number. (And note that the most significant bit of these 8 becomes the sign bit.)
在计算上,这对应于从原始数字中提取 8 个最低有效位。(请注意,这 8 个中的最高有效位成为符号位。)
Note that in other languages this behaviour is not defined (e.g. C and C++).
请注意,在其他语言中,此行为未定义(例如 C 和 C++)。