[英]Odd behavior when Java converts int to byte?
int i =132;
byte b =(byte)i; System.out.println(b);
令人難以置信。 為什么輸出-124
?
在 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,這是正數),因此 Java 將字節中的原始 8 位讀取為正值。
132
位(基數 10 )是1000_0100
位(基數 2 ),Java 以 32 位存儲int
:
0000_0000_0000_0000_0000_0000_1000_0100
int-to-byte 的算法是左截斷的; System.out.println
算法是二進制補碼(二進制補碼是如果最左邊的位是1
,則解釋為負的補碼(反轉位)減一。); 因此System.out.println(int-to-byte(
))
是:
0000_0000_0000_0000_0000_0000_1000_0100
) [)))] )1000_0100
[)))] )1000_0100
))))1000_0011
)))0111_1100
))Java 中的字節是有符號的,因此它的范圍是 -2^7 到 2^7-1 - 即 -128 到 127。由於 132 大於 127,所以最終會環繞到 132-256=-124。 也就是說,本質上增加或減少了 256 (2^8) 次,直到它落入范圍內。
有關更多信息,您可能需要閱讀二進制補碼。
132 超出了 -128 到 127(Byte.MIN_VALUE 到 Byte.MAX_VALUE)的字節范圍,而是將 8 位值的最高位視為有符號的,這表明在這種情況下它是負數。 所以數字是 132 - 256 = -124。
這是一個非常機械的方法,沒有分散注意力的理論:
這種更實用的方法與上面的許多理論答案一致。 所以,那些仍在閱讀那些說要使用模的 Java 書籍的人,這絕對是錯誤的,因為我上面概述的 4 個步驟絕對不是模運算。
在 Java 中, byte
(N=8) 和int
(N=32) 由上圖所示的 2s 補碼表示。
從等式來看,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
通常在書中,您會發現從 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);
}
}
}
模擬其工作方式的快速算法如下:
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;
}
如果你想從數學上理解這一點,比如它是如何工作的
所以基本上數字 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)
注意:它不會考慮小數點后的數字。
從概念上講,對您的數字進行 256 的重復減法,直到它在 -128 到 +127 的范圍內。 因此,在您的情況下,您從 132 開始,然后一步以 -124 結束。
在計算上,這對應於從原始數字中提取 8 個最低有效位。 (請注意,這 8 個中的最高有效位成為符號位。)
請注意,在其他語言中,此行為未定義(例如 C 和 C++)。
將“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
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.