Mam następujący kod ...
int Val=-32768;
String Hex=Integer.toHexString(Val);
To się równa ffff8000
int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
Tak więc początkowo konwertuje wartość -32768 na ciąg szesnastkowy ffff8000, ale potem nie może przekonwertować ciągu szesnastkowego z powrotem na liczbę całkowitą.
W .Net
tym działa tak, jak się spodziewałem, i returns -32768
.
Wiem, że mógłbym napisać własną małą metodę konwertowania tego samodzielnie, ale zastanawiam się tylko, czy coś mi brakuje, czy to naprawdę błąd?
int firstAttempt = 5;
Odpowiedzi:
Przepełnia się, ponieważ liczba jest ujemna.
Spróbuj tego i zadziała:
int n = (int) Long.parseLong("ffff8000", 16);
źródło
String Hex=Integer.toHexString("xyz");
jak odzyskać ciąg znaków z hexa jako „xyz”int val = -32768; String hex = Integer.toHexString(val); int parsedResult = (int) Long.parseLong(hex, 16); System.out.println(parsedResult);
Tak możesz to zrobić.
Powód, dla którego to nie działa w twój sposób:
Integer.parseInt
przyjmuje int ze znakiem, podczas gdytoHexString
daje wynik bez znaku. Więc jeśli wstawisz coś wyższego niż0x7FFFFFF
, błąd zostanie wyrzucony automatycznie. Jeślilong
zamiast tego przeanalizujesz go , nadal będzie podpisany. Ale kiedy rzucisz go z powrotem na int, przepełni się do prawidłowej wartości.źródło
int
do Hex:Szesnastkowo do
int
:Integer.valueOf(hexString, 16).intValue();
Możesz także użyć
long
zamiastint
(jeśli wartość nie mieści się wint
granicach):Szesnastkowo do
long
:Long.valueOf(hexString, 16).longValue()
long
do Hexźródło
Warto wspomnieć, że Java 8 ma metody
Integer.parseUnsignedInt
iLong.parseUnsignedLong
robi to, czego chciałeś, w szczególności:Integer.parseUnsignedInt("ffff8000",16) == -32768
Nazwa jest nieco myląca, ponieważ analizuje liczbę całkowitą ze znakiem z ciągu szesnastkowego, ale działa.
źródło
Spróbuj użyć klasy BigInteger, działa.
int Val=-32768; String Hex=Integer.toHexString(Val); //int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int" //int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int" BigInteger i = new BigInteger(Hex,16); System.out.println(i.intValue());
źródło
Ponieważ Integer.toHexString (byte / integer) nie działa, gdy próbujesz przekonwertować podpisane bajty, takie jak zdekodowane znaki UTF-16, musisz użyć:
Integer.toString(byte/integer, 16);
lub
String.format("%02X", byte/integer);
Odwróć, którego możesz użyć
Integer.parseInt(hexString, 16);
źródło
Metoda parseInt Javy jest w praktyce zbiorem kodu zjadającego wartość szesnastkową „false”: jeśli chcesz przetłumaczyć wartość -32768, powinieneś zamienić wartość bezwzględną na szesnastkową, a następnie wstawić ciąg przedrostkiem „-”.
Oto przykład pliku Integer.java:
public static int parseInt(String s, int radix)
Opis jest dość wyraźny:
* Parses the string argument as a signed integer in the radix * specified by the second argument. The characters in the string ... ... * parseInt("0", 10) returns 0 * parseInt("473", 10) returns 473 * parseInt("-0", 10) returns 0 * parseInt("-FF", 16) returns -255
źródło
Używanie
Integer.toHexString(...)
to dobra odpowiedź. Ale osobiście wolę używaćString.format(...)
.Wypróbuj tę próbkę jako test.
byte[] values = new byte[64]; Arrays.fill(values, (byte)8); //Fills array with 8 just for test String valuesStr = ""; for(int i = 0; i < values.length; i++) valuesStr += String.format("0x%02x", values[i] & 0xff) + " "; valuesStr.trim();
źródło
Poniższy kod zadziała:
int a=-32768; String a1=Integer.toHexString(a); int parsedResult=(int)Long.parseLong(a1,16); System.out.println("Parsed Value is " +parsedResult);
źródło
Hehe, ciekawy. Myślę, że to „intencjonalny błąd”, że tak powiem.
Podstawowym powodem jest sposób zapisu klasy Integer. Zasadniczo parseInt jest „zoptymalizowany” dla liczb dodatnich. Kiedy analizuje ciąg, buduje skumulowany wynik, ale zanegowany. Następnie odwraca znak wyniku końcowego.
Przykład:
66 = 0x42
przeanalizowane jak:
4*(-1) = -4 -4 * 16 = -64 (hex 4 parsed) -64 - 2 = -66 (hex 2 parsed) return -66 * (-1) = 66
Spójrzmy teraz na Twój przykład FFFF8000
16*(-1) = -16 (first F parsed) -16*16 = -256 -256 - 16 = -272 (second F parsed) -272 * 16 = -4352 -4352 - 16 = -4368 (third F parsed) -4352 * 16 = -69888 -69888 - 16 = -69904 (forth F parsed) -69904 * 16 = -1118464 -1118464 - 8 = -1118472 (8 parsed) -1118464 * 16 = -17895552 -17895552 - 0 = -17895552 (first 0 parsed) Here it blows up since -17895552 < -Integer.MAX_VALUE / 16 (-134217728). Attempting to execute the next logical step in the chain (-17895552 * 16) would cause an integer overflow error.
Edycja (dodawanie): aby parseInt () działało „konsekwentnie” dla -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, musieliby zaimplementować logikę „rotacji” po osiągnięciu -Integer.MAX_VALUE w skumulowany wynik, zaczynając od maksymalnego końca zakresu liczb całkowitych i kontynuując w dół od tego miejsca. Dlaczego tego nie zrobili, należałoby zapytać Josha Blocha lub tego, kto to wdrożył. To może być tylko optymalizacja.
Jednak,
Hex=Integer.toHexString(Integer.MAX_VALUE); System.out.println(Hex); System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));
działa dobrze, tylko z tego powodu. W źródle Integer można znaleźć ten komentarz.
// Accumulating negatively avoids surprises near MAX_VALUE
źródło
// Accumulating negatively avoids surprises near MAX_VALUE
-> ale wprowadza niespodzianki niższe 0 ^^