int i =132;
byte b =(byte)i; System.out.println(b);
Mindboggling。为什么输出-124
?
答案 0 :(得分:165)
在Java中,int
是32位。 byte
为8 bits
。
Java中的大多数原始类型都是签名的,byte
,short
,int
和long
以二进制补码编码。 (char
类型是无符号的,符号的概念不适用于boolean
。)
在此数字方案中,最高有效位指定数字的符号。如果需要更多位,则将最高位(“MSB”)简单地复制到新MSB。
所以如果你有字节255
:11111111
并且您希望将其表示为int
(32位),只需将1复制到左侧24次。
现在,读取负二进制补码的一种方法是从最低有效位开始,向左移动直到找到第一个1,然后反转每一位。结果数字是该数字的正面版本
例如:11111111
转到00000001
= -1
。这就是Java将作为值显示的内容。
您可能想要做的是知道字节的无符号值。
您可以使用位掩码来删除除最不重要的8位之外的所有内容。 (0xff的)
所以:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
会打印出来:"Signed: -1 Unsigned: 255"
这里到底发生了什么?
我们使用按位AND来屏蔽所有无关的符号位(最低有效8位左边的1)。 当int转换为字节时,Java会截断最左边的24位
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
由于第32位现在是符号位而不是第8位(并且我们将符号位设置为0,这是正数),因此字节的原始8位由Java读取为正值。
答案 1 :(得分:87)
132
为1000_0100
位(base 2),Java存储int
为32位:
0000_0000_0000_0000_0000_0000_1000_0100
int-to-byte的算法是left-truncate; System.out.println
的算法是two's-complement(如果最左边的位是1
则是二进制补码,解释为负one's-complement(反转位)减-1。);因此System.out.println(int-to-byte(
))
是:
0000_0000_0000_0000_0000_0000_1000_0100
)[)))))1000_0100
[)))))1000_0100
))))1000_0011
)))0111_1100
))答案 2 :(得分:23)
字节是有符号的,因此它具有-2 ^ 7到2 ^ 7-1的范围 - 即-128到127。 由于132高于127,你最终会回绕到132-256 = -124。也就是说,基本上加上或减去256(2 ^ 8)直到它落入范围。
有关详细信息,您可能需要阅读two's complement。
答案 3 :(得分:16)
132超出字节范围-128到127(Byte.MIN_VALUE到Byte.MAX_VALUE) 相反,8位值的最高位被视为有符号,表示在这种情况下它是负数。所以数字是132 - 256 = -124。
答案 4 :(得分:3)
这是一种非常机械的方法,没有分散注意力的理论:
这种更实用的方法符合上面的理论答案。所以,那些仍在阅读那些使用modulo的Java书籍的人,这绝对是错误的,因为我上面概述的4个步骤绝对不是模运算。
答案 5 :(得分:3)
在Java中,byte
(N = 8)和int
(N = 32)由上面显示的2s补码表示。
从等式中, 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
答案 6 :(得分:2)
通常在书中你会发现从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);
}
}
}
答案 7 :(得分:2)
模拟其工作方式的快速算法如下:
public int toByte(int number) {
int tmp = number & 0xff
return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}
这怎么工作?期待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;
}
答案 8 :(得分:0)
从概念上讲,对你的数字进行256次重复减法,直到它在-128到+127的范围内。因此,在您的情况下,您从132开始,然后一步结束-124。
计算上,这对应于从原始数字中提取8个最低有效位。 (并注意这8个中最重要的位成为符号位。)
请注意,在其他语言中,未定义此行为(例如,C和C ++)。
答案 9 :(得分:0)
如果您想从数学上理解它,例如它是如何工作的
因此基本上b / w -128到127的数字将与它们的十进制值相同,高于其十进制值(您的数字-256)。
例如132,答案将是 132-256 =-124 即
256 +您的电话号码答案 256 +(-124)是132
另一个例子
double a = 295.04;
int b = 300;
byte c = (byte) a;
byte d = (byte) b; System.out.println(c + " " + d);
输出将为39 44
(295-256)(300-256)
注意:它将不考虑小数点后的数字。
答案 10 :(得分:0)
把'int'转换成'byte'就像把大对象装进小盒子
如果登录 -ve 取 2 的补码
示例 1:让数字为 130
第 1 步:130 位 =1000 0010
第 2 步:判断第 1 个 7 位和第 8 位是符号(1=-ve 和 =+ve)
第 3 步:将第 1 个 7 位转换为 2 的补码
000 0010
-------------
111 1101
add 1
-------------
111 1110 =126
第 4 步:第 8 位为“1”,因此符号为 -ve
第 5 步:130 的字节=-126
示例 2:让数字为 500
步骤 1:500 位 0001 1111 0100
第 2 步:考虑第 1 个 7 位 =111 0100
第 3 步:剩下的位是 '11' 给出 -ve 符号
第 4 步:接受 2 的赞美
111 0100
-------------
000 1011
add 1
-------------
000 1100 =12
第 5 步:500 的字节=-12
示例 3:数字=300
300=1 0010 1100
1st 7 bits =010 1100
remaining bit is '0' sign =+ve need not take 2's compliment for +ve sign
hence 010 1100 =44
byte(300) =44
答案 11 :(得分:-1)
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