Próbuję przekonwertować podpisany bajt na niepodpisany. Problem polega na tym, że dane, które otrzymuję, są niepodpisane, a Java nie obsługuje bajtu bez znaku, więc kiedy odczytuje dane, traktuje je jako podpisane.
Próbowałem go przekonwertować za pomocą następującego rozwiązania, które otrzymałem z Stack Overflow.
public static int unsignedToBytes(byte a)
{
int b = a & 0xFF;
return b;
}
Ale kiedy ponownie jest konwertowany na bajty, otrzymuję te same podpisane dane. Próbuję użyć tych danych jako parametru funkcji Java, która akceptuje tylko bajt jako parametr, więc nie mogę użyć żadnego innego typu danych. Jak mogę rozwiązać ten problem?
Odpowiedzi:
Nie jestem pewien, czy rozumiem twoje pytanie.
Właśnie próbowałem tego i dla bajtu -12 (wartość ze znakiem) zwrócił liczbę całkowitą 244 (równoważną wartości bajtu bez znaku, ale wpisaną jako
int
):Czy to jest to co chcesz robić?
Java nie pozwala wyrazić 244 jako
byte
wartość, jako że C. Aby wyrazić całkowite dodatnie powyżejByte.MAX_VALUE
(127) trzeba użyć innego rodzaju całkowitą, jakshort
,int
lublong
.źródło
byte b = (byte)unsignedToBytes((byte) -12);
teraz spróbuj wydrukować bFakt, że prymitywy są podpisywane w Javie, nie ma znaczenia dla ich reprezentacji w pamięci / tranzycie - bajt ma zaledwie 8 bitów i to, czy interpretujesz go jako zakres podpisany, czy nie, zależy od ciebie. Nie ma magicznej flagi, która mówi „to jest podpisane” lub „to jest niepodpisane”.
Po podpisaniu prymitywów kompilator Java uniemożliwia przypisanie bajtu wartości wyższej niż +127 (lub mniejszej niż -128). Jednak nic nie powstrzyma cię przed spuszczeniem int (lub krótkiego) w celu osiągnięcia tego:
źródło
Kompletny przewodnik dotyczący pracy z niepodpisanymi bajtami w Javie:
Niepodpisany bajt w Javie
(Źródło tej odpowiedzi.)
Język Java nie zapewnia
unsigned
słowa kluczowego. Abyte
zgodnie ze specyfikacją języka reprezentuje wartość z zakresu od –128 do 127. Na przykład, jeślibyte
rzutuje się naint
Javę, interpretuje pierwszy bit jako znak i używa rozszerzenia znaku .To powiedziawszy, nic nie stoi na przeszkodzie, abyś zobaczył
byte
po prostu 8 bitów i zinterpretował te bity jako wartość od 0 do 255. Pamiętaj tylko, że nic nie możesz zrobić, aby zmusić swoją interpretację do użycia metody innej osoby. Jeśli metoda przyjmuje wartość abyte
, wówczas metoda ta przyjmuje wartość z zakresu od –128 do 127, chyba że wyraźnie zaznaczono inaczej.Oto kilka przydatnych konwersji / manipulacji dla Twojej wygody:
Konwersje do / z int
(Lub, jeśli korzystasz z Java 8+, użyj
Byte.toUnsignedInt
.)Analiza / formatowanie
Najlepszym sposobem jest użycie powyższych konwersji:
Arytmetyka
Reprezentacja z 2 uzupełnieniami „po prostu działa” na dodawanie, odejmowanie i mnożenie:
Podział wymaga ręcznej konwersji argumentów:
źródło
W Javie nie ma prymitywnych bajtów bez znaku. Zwykle używa się większego typu:
źródło
Myślę, że inne odpowiedzi obejmowały reprezentację pamięci, a sposób, w jaki sobie z nimi radzisz, zależy od kontekstu, w jaki planujesz z niej korzystać. Dodam, że Java 8 dodała pewne wsparcie dla radzenia sobie z typami niepodpisanymi . W takim przypadku możesz użyć
Byte.toUnsignedInt
źródło
Dodatkowa uwaga, jeśli chcesz ją wydrukować, możesz po prostu powiedzieć
źródło
println(b & 0xff)
wystarczyJeśli uważasz, że szukasz czegoś takiego.
źródło
Adamski udzielił najlepszej odpowiedzi, ale nie jest ona kompletna, więc przeczytaj jego odpowiedź, ponieważ wyjaśnia szczegóły, których nie jestem.
Jeśli masz funkcję systemową, która wymaga przekazania bajtu niepodpisanego, możesz przekazać bajt podpisany, ponieważ automatycznie potraktuje go jako bajt niepodpisany.
Więc jeśli funkcja systemowa wymaga czterech bajtów, na przykład 192 168 0 1 jako bajty niepodpisane, możesz przekazać -64 -88 0 1, a funkcja będzie nadal działać, ponieważ przekazanie ich do funkcji spowoduje ich cofnięcie podpisu .
Jest jednak mało prawdopodobne, aby ten problem występował, ponieważ funkcje systemowe są ukryte za klasami w celu zapewnienia zgodności między platformami, chociaż niektóre metody odczytu java.io zwracają nieobsługiwane bajty jako int.
Jeśli chcesz, aby to działało, spróbuj zapisać podpisane bajty w pliku i odczytać je jako bajty niepodpisane.
źródło
Możesz także:
Wyjaśnienie:
powiedzmy
a = (byte) 133;
W pamięci jest przechowywany jako: „1000 0101” (0x85 w systemie szesnastkowym)
Tak więc jego reprezentacja tłumaczy unsigned = 133, podpisany = -123 (jako uzupełnienie 2)
Po wykonaniu przesunięcia w lewo o 24 bity w lewo, wynikiem jest teraz 4-bajtowa liczba całkowita reprezentowana przez:
„10000101 00000000 00000000 00000000” (lub „0x85000000” w systemie szesnastkowym)
Następnie mamy
i przesuwa się ponownie na prawych 24 bitach, ale wypełnia się wiodącymi zerami. Wynika z tego, że:
„00000000 00000000 00000000 10000101” (lub „0x00000085” w systemie szesnastkowym)
i to jest niepodpisana reprezentacja równa 133.
Jeśli spróbujesz rzucić,
a = (int) a;
to co by się stało, zachowa reprezentację bajtu z dopełnieniem 2 i zapisze go jako int również jako dopełnienie 2:(int) „10000101” ---> „11111111 11111111 11111111 10000101”
A to tłumaczy się jako: -123
źródło
java.lang.Byte.toUnsignedInt(byte value)
. A jeśli nie używasz jeszcze Java 8, zaktualizuj jak najszybciej. Java 7 i wcześniejsze wersje są już wycofane.Nie różni się to zasadniczo od funkcji akceptującej liczbę całkowitą, do której chcesz przekazać wartość większą niż 2 ^ 32-1.
To brzmi jak zależy od tego, jak funkcja jest zdefiniowana i udokumentowana; Widzę trzy możliwości:
Może jawnie udokumentować, że funkcja traktuje bajt jako wartość bez znaku, w którym to przypadku funkcja prawdopodobnie powinna zrobić to, czego się spodziewasz, ale wydaje się, że została źle zaimplementowana. W przypadku liczby całkowitej funkcja prawdopodobnie zadeklaruje parametr jako liczbę całkowitą bez znaku, ale nie jest to możliwe w przypadku bajtu.
Może udokumentować, że wartość tego argumentu musi być większa niż (lub być może równa) zero, w którym to przypadku niewłaściwie używasz funkcji (przekazując parametr spoza zakresu), oczekując, że zrobi więcej, niż to zostało zaprojektowane robić. Przy pewnym poziomie obsługi debugowania można oczekiwać, że funkcja wyrzuci wyjątek lub nie powiedzie się asercja.
Dokumentacja może nic nie mówić, w takim przypadku parametr ujemny jest, no cóż, parametrem ujemnym, a to, czy ma to jakiekolwiek znaczenie, zależy od tego, co robi funkcja. Jeśli to nie ma znaczenia, być może funkcja powinna być naprawdę zdefiniowana / udokumentowana jako (2). Jeśli ma to znaczenie w sposób nieoczywisty (np. Wartości nieujemne są używane do indeksowania do tablicy, a wartości ujemne są używane do indeksowania z powrotem od końca tablicy, więc -1 oznacza ostatni element), dokumentacja powinna powiedzieć, co to znaczy oznacza i spodziewałbym się, że i tak nie chcesz tego robić.
źródło
Jeśli masz funkcję, której należy przekazać bajt podpisany, czego oczekujesz, jeśli przekażesz bajt niepodpisany?
Dlaczego nie możesz użyć innego typu danych?
Zwykle można użyć bajtu jako bajtu niepodpisanego z prostymi tłumaczeniami lub bez tłumaczenia. Wszystko zależy od tego, jak jest używany. Musisz wyjaśnić, co zamierzasz z tym zrobić.
źródło
Chociaż może wydawać się denerwujące (pochodzące z C), że Java nie zawierała bajtu niepodpisanego w języku, to naprawdę nie jest wielka sprawa, ponieważ prosta operacja „b & 0xFF” daje niepodpisaną wartość (podpisanego) bajtu b w (rzadkim) sytuacje, w których jest to rzeczywiście potrzebne. Bity tak naprawdę się nie zmieniają - tylko interpretacja (co jest ważne tylko podczas wykonywania na przykład niektórych operacji matematycznych na wartościach).
źródło
x & 0xFF
wszędzie, gdzie jest to potrzebne, lub powtarzacie coś takiego jakbehaveLikeAnUnsignedByte(x)
wszędzie. Jest to potrzebne dla każdego miejsca, w którym używasz wartości bajtu lub tablicy bajtów, które muszą być niepodpisane, nie ma możliwego sposobu na uniknięcie tego powtórzenia. Nie można napisać implementacji protokołu, który odczytuje i zapisuje wartości bajtów za pomocą tylko jednego odwołania do zmiennej bajtowej. Twój uproszczony pogląd może wyjaśniać, dlaczego nigdy nie chcieli go naprawić.W Javie nie ma bajtu bez znaku, ale jeśli chcesz wyświetlić bajt, możesz:
Wynik:
Aby uzyskać więcej informacji, sprawdź, jak wyświetlić wartość szesnastkową / bajtową w Javie .
źródło
java.lang.Byte.toUnsignedInt(byte value);
istnieje po to.Zgodnie z ograniczeniami w Javie bajt bez znaku jest prawie niemożliwy w obecnym formacie typu danych. Możesz wybrać inne biblioteki innego języka dla tego, co wdrażasz, a następnie możesz do nich zadzwonić za pomocą JNI .
źródło
Tak i nie. Przekopałem się z tym problemem. Jak rozumiem to:
Faktem jest, że Java podpisała interger -128 do 127. Możliwe jest przedstawienie niepodpisanego w java z:
Jeśli na przykład dodasz numer podpisany -12, aby się nie podpisać, otrzymasz 244. Ale możesz użyć tego numeru ponownie w podpisanym, musisz go zmienić z powrotem na podpisany i będzie to ponownie -12.
Jeśli spróbujesz dodać 244 do bajtu java, otrzymasz outOfIndexException.
Twoje zdrowie..
źródło
java.lang.Byte.toUnsignedInt(byte value);
istnieje po to.Jeśli chcesz napisać bajty bez znaku w Javie, po prostu odejmij 256 od liczby, którą jesteś zainteresowany. Spowoduje to uzupełnienie dwóch o wartość ujemną, czyli pożądaną liczbę w bajtach bez znaku.
Przykład:
Musisz użyć takich brudnych hacków podczas korzystania z leJOS do programowania klocka NXT .
źródło
speed_unsigned
jest podpisana. Wydrukuj i zobacz. (I- 256
tutaj nic nie osiąga.)