int i =132;
byte b =(byte)i; System.out.println(b);
Tâm boggling. Tại sao là đầu ra -124?
int i =132;
byte b =(byte)i; System.out.println(b);
Tâm boggling. Tại sao là đầu ra -124?
Câu trả lời:
Trong Java, một intlà 32 bit. A bytelà 8 bits.
Hầu hết các loại nguyên thủy trong Java được ký kết, và byte, short, int, và longđược mã hóa trong bổ sung hai nhân. ( charLoại không dấu và khái niệm về một dấu hiệu không được áp dụng cho boolean.)
Trong sơ đồ số này, bit quan trọng nhất chỉ định dấu của số. Nếu cần nhiều bit hơn, bit quan trọng nhất ("MSB") chỉ đơn giản được sao chép sang MSB mới.
Vì vậy, nếu bạn có byte 255: 11111111
và bạn muốn biểu diễn nó dưới dạng int(32 bit), bạn chỉ cần sao chép 1 sang trái 24 lần.
Bây giờ, một cách để đọc số bổ sung của hai số âm là bắt đầu với bit có trọng số thấp nhất, di chuyển sang trái cho đến khi bạn tìm thấy số 1 đầu tiên, sau đó đảo ngược từng bit sau đó. Số kết quả là phiên bản dương của số đó
Ví dụ: 11111111đi đến 00000001= -1. Đây là những gì Java sẽ hiển thị như là giá trị.
Những gì bạn có thể muốn làm là biết giá trị không dấu của byte.
Bạn có thể thực hiện điều này với một bitmask xóa mọi thứ trừ 8 bit quan trọng nhất. (0xff)
Vì thế:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
Sẽ in ra: "Signed: -1 Unsigned: 255"
Điều gì thực sự xảy ra ở đây?
Chúng tôi đang sử dụng bitwise AND để che dấu tất cả các bit ký hiệu không liên quan (1 bit ở bên trái của 8 bit có ý nghĩa nhỏ nhất.) Khi một int được chuyển đổi thành một byte, Java tách ra 24 bit bên trái
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Do bit thứ 32 bây giờ là bit dấu thay vì bit thứ 8 (và chúng tôi đặt bit dấu thành 0 là dương), 8 bit gốc từ byte được Java đọc làm giá trị dương.
signedByte & (0xff)là 0xffmột nghĩa đen, do đó SignByte được thăng cấp thành một số nguyên trước khi thao tác bitwise được thực hiện.
132tính bằng chữ số ( cơ sở 10 ) tính 1000_0100bằng bit ( cơ sở 2 ) và Java lưu trữ inttrong 32 bit:
0000_0000_0000_0000_0000_0000_1000_0100
Thuật toán cho int-to-byte là cắt ngắn; Thuật toán cho System.out.printlnlà hai phần bù (Phần bù hai là nếu bit ngoài cùng bên trái là 1, diễn giải dưới dạng phần bù âm (phần tử đảo ngược) âm trừ một phần một.); Như vậy System.out.println(int-to-byte( ))là:
0000_0000_0000_0000_0000_0000_1000_0100) [)))])1000_0100[)))])1000_0100))))1000_0011)))0111_1100))intđến a bytelà một sự hội tụ mất mát (tức là thông tin bị mất). Do đó, không có cách nào để chuyển đổi nó trở lại intgiá trị ban đầu của nó .
byte trong Java được ký, do đó, nó có phạm vi -2 ^ 7 đến 2 ^ 7-1 - tức là, -128 đến 127. Vì 132 ở trên 127, nên cuối cùng bạn sẽ bao quanh khoảng 132-256 = -124. Đó là, về cơ bản, 256 (2 ^ 8) được thêm hoặc trừ cho đến khi nó rơi vào phạm vi.
Để biết thêm thông tin, bạn có thể muốn đọc lên phần bổ sung của hai .
132 nằm ngoài phạm vi của một byte là -128 đến 127 (Byte.MIN_VALUE thành Byte.MAX_VALUE) Thay vào đó, bit trên cùng của giá trị 8 bit được coi là ký hiệu cho thấy nó âm trong trường hợp này. Vậy số đó là 132 - 256 = -124.
đây là một phương pháp rất cơ học mà không có lý thuyết gây mất tập trung:
Phương pháp thực tế hơn này phù hợp với nhiều câu trả lời lý thuyết ở trên. Vì vậy, những người vẫn đọc những cuốn sách Java nói rằng sử dụng modulo, điều này hoàn toàn sai vì 4 bước tôi đã nêu ở trên chắc chắn không phải là một hoạt động modulo.
http://iiti.ac.in/people/~tanimad/JavaTheCompleteReference.pdftrang 59
Trong Java, byte(N = 8) và int(N = 32) được biểu thị bằng phần bù 2s được hiển thị ở trên.
Từ phương trình, 7 là âm cho bytenhưng dương cho 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
thông thường trong các cuốn sách, bạn sẽ tìm thấy lời giải thích về việc truyền từ int sang byte như được thực hiện bởi phép chia mô đun. điều này không hoàn toàn chính xác như được hiển thị bên dưới những gì thực sự xảy ra là 24 bit quan trọng nhất từ giá trị nhị phân của số int bị loại bỏ để lại sự nhầm lẫn nếu bit ngoài cùng bên trái được đặt chỉ định số là âm
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);
}
}
}
Một thuật toán nhanh mô phỏng cách thức hoạt động của nó là như sau:
public int toByte(int number) {
int tmp = number & 0xff
return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}
Làm thế nào điều này làm việc? Nhìn vào câu trả lời daixtr . Việc thực hiện thuật toán chính xác được ghi lại trong câu trả lời của ông là như sau:
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;
}
Nếu bạn muốn hiểu điều này một cách toán học, như cách nó hoạt động
vì vậy về cơ bản, các số b / w -128 đến 127 sẽ được viết giống như giá trị thập phân của chúng, cao hơn số đó (số của bạn - 256).
ví dụ. 132, câu trả lời sẽ là 132 - 256 = - 124 tức là
256 + câu trả lời của bạn trong số 256 + (-124) là 132
Một vi dụ khac
double a = 295.04;
int b = 300;
byte c = (byte) a;
byte d = (byte) b; System.out.println(c + " " + d);
đầu ra sẽ là 39 44
(295 - 256) (300 - 256)
LƯU Ý: nó sẽ không xem xét các số sau số thập phân.
Về mặt khái niệm, phép trừ lặp lại 256 được thực hiện cho số của bạn, cho đến khi nó nằm trong phạm vi -128 đến +127. Vì vậy, trong trường hợp của bạn, bạn bắt đầu với 132, sau đó kết thúc với -124 trong một bước.
Tính toán, điều này tương ứng với việc trích xuất 8 bit có ý nghĩa nhỏ nhất từ số ban đầu của bạn. (Và lưu ý rằng bit quan trọng nhất trong số 8 này trở thành bit dấu.)
Lưu ý rằng trong các ngôn ngữ khác, hành vi này không được xác định (ví dụ: C và C ++).
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