int i =132;
byte b =(byte)i; System.out.println(b);
Oszałamiające. Dlaczego jest wyjście -124?
Odpowiedzi:
W Javie jest intto 32 bity. A bytewynosi 8 bits.
Większość prymitywne typy w Javie są podpisane, a byte, short, int, i longsą zakodowane w dwóch uzupełnień. ( charTyp jest bez znaku, a pojęcie znaku nie ma zastosowania boolean).
W tym schemacie liczbowym najbardziej znaczący bit określa znak liczby. Jeśli potrzeba więcej bitów, najbardziej znaczący bit („MSB”) jest po prostu kopiowany do nowego MSB.
Więc jeśli masz bajt 255: 11111111
i chcesz przedstawić go jako int(32 bity), po prostu skopiuj 1 z lewej strony 24 razy.
Teraz jednym ze sposobów odczytania liczby uzupełnienia ujemnego do dwóch jest rozpoczęcie od najmniej znaczącego bitu, przesuwanie w lewo, aż znajdziesz pierwszą 1, a następnie odwracanie każdego bitu. Wynikowa liczba jest dodatnią wersją tej liczby
Na przykład: 11111111idzie do 00000001= -1. To właśnie Java wyświetli wartość.
To, co prawdopodobnie chcesz zrobić, to znać wartość bajtu bez znaku.
Możesz to osiągnąć za pomocą maski bitowej, która usuwa wszystko oprócz najmniej znaczących 8 bitów. (0xff)
Więc:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
Wydrukowałoby: "Signed: -1 Unsigned: 255"
Co się tu właściwie dzieje?
Używamy bitowego AND do zamaskowania wszystkich dodatkowych bitów znaku (jedynek po lewej stronie najmniej znaczących 8 bitów). Kiedy int jest konwertowany na bajt, Java odcina skrajne lewe 24 bity
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Ponieważ 32. bit jest teraz bitem znaku zamiast ósmego (i ustawiamy bit znaku na 0, który jest dodatni), oryginalne 8 bitów z bajtu jest odczytywane przez Javę jako wartość dodatnia.
signedByte & (0xff)tak, że 0xffjest to literał międzygałowy, dlatego signedByte jest promowane do liczby całkowitej przed wykonaniem operacji bitowej.
132cyframi ( podstawa 10 ) jest 1000_0100bitami ( podstawa 2 ), a Java przechowuje intw 32 bitach:
0000_0000_0000_0000_0000_0000_1000_0100
Algorytm int-to-byte jest skracany do lewej; Algorytm System.out.printlnjest uzupełnienie do dwóch (uzupełnienie do dwóch jest, jeśli bit od lewej 1, interpretować jako negatywne one's-dopełniacza (inwertowanym bitów) minus jeden.); Tak więc System.out.println(int-to-byte( ))jest:
0000_0000_0000_0000_0000_0000_1000_0100) [)))])1000_0100[)))])1000_0100))))1000_0011)))0111_1100))intna a bytejest konwersją stratną (tj. Utrata informacji). Dlatego nie ma możliwości przekonwertowania go z powrotem do pierwotnej intwartości.
bajt w Javie jest podpisany, więc ma zakres od -2 ^ 7 do 2 ^ 7-1 - tj. od -128 do 127. Ponieważ 132 jest powyżej 127, kończy się zawijanie wokół 132-256 = -124. Oznacza to, że zasadniczo 256 (2 ^ 8) jest dodawane lub odejmowane, aż znajdzie się w zakresie.
Aby uzyskać więcej informacji, możesz przeczytać więcej na temat uzupełnień do dwóch .
132 znajduje się poza zakresem bajtu, który wynosi od -128 do 127 (Byte.MIN_VALUE do Byte.MAX_VALUE) Zamiast tego górny bit wartości 8-bitowej jest traktowany jako znak ze znakiem, co oznacza, że w tym przypadku jest ujemny. Więc liczba to 132 - 256 = -124.
oto bardzo mechaniczna metoda bez rozpraszających teorii:
Ta bardziej praktyczna metoda jest zgodna z dużo teoretycznymi odpowiedziami powyżej. Tak więc ci, którzy nadal czytają te książki o Javie, które mówią, że używają modulo, jest to zdecydowanie błędne, ponieważ 4 kroki, które opisałem powyżej, zdecydowanie nie są operacją modulo.
http://iiti.ac.in/people/~tanimad/JavaTheCompleteReference.pdfstrona 59
Równanie uzupełnienia do dwóch:
W Javie, byte(N = 8) i int(N = 32) są reprezentowane przez uzupełnienie do 2s pokazane powyżej.
Z równania 7 jest ujemne dla, byteale dodatnie dla 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
często w książkach można znaleźć wyjaśnienie rzutowania z int na bajt jako wykonywane przez dzielenie modułu. nie jest to do końca poprawne, jak pokazano poniżej, co faktycznie się dzieje, to 24 najbardziej znaczące bity z wartości binarnej liczby int są odrzucane, pozostawiając zamieszanie, jeśli ustawiony jest pozostały skrajny lewy bit, który oznacza liczbę jako ujemną
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);
}
}
}
Szybki algorytm symulujący sposób działania jest następujący:
public int toByte(int number) {
int tmp = number & 0xff
return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}
Jak to działa? Spójrz na odpowiedź daixtr . Implementacja dokładnego algorytmu opisanego w jego odpowiedzi jest następująca:
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;
}
Jeśli chcesz zrozumieć to matematycznie, powiedz, jak to działa
więc zasadniczo liczby b / w -128 do 127 będą zapisywane tak samo jak ich wartość dziesiętna, powyżej jej (twoja liczba - 256).
na przykład. 132, odpowiedź będzie 132 - 256 = - 124 tj
256 + twoja odpowiedź w numerze 256 + (-124) to 132
Inny przykład
double a = 295.04;
int b = 300;
byte c = (byte) a;
byte d = (byte) b; System.out.println(c + " " + d);
Wynik wyniesie 39 44
(295–256) (300–256)
UWAGA: nie będzie uwzględniać liczb po przecinku.
Koncepcyjnie do Twojej liczby odejmowane są wielokrotne odejmowania 256, aż znajdzie się w zakresie od -128 do +127. Więc w twoim przypadku zaczynasz od 132, a kończysz na -124 w jednym kroku.
Pod względem obliczeniowym odpowiada to wyodrębnieniu 8 najmniej znaczących bitów z pierwotnej liczby. (Zauważ, że najbardziej znaczący bit z tych 8 staje się bitem znaku).
Zauważ, że w innych językach to zachowanie nie jest zdefiniowane (np. C i 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