85

私は次のコードを持っています...

int Val=-32768;
String Hex=Integer.toHexString(Val);

これはに相当しますffff8000

int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex);  // Error "Invalid Int"

したがって、最初は、値-32768を16進文字列ffff8000に変換しますが、その後、16進文字列を整数に戻すことはできません。

それで.Net私が期待するように動作します、そしてreturns -32768

これを自分で変換するための独自の小さなメソッドを作成できることは知っていますが、何かが足りないのか、それとも本当にバグなのか疑問に思っています。

4

10 に答える 10

79
int val = -32768;
String hex = Integer.toHexString(val);

int parsedResult = (int) Long.parseLong(hex, 16);
System.out.println(parsedResult);

それがあなたがそれをすることができる方法です。

それがうまくいかない理由:符号付きInteger.parseInt整数を取り、toHexString符号なし結果を生成します。したがって、より高い値を挿入する0x7FFFFFFと、エラーが自動的にスローされます。代わりに解析するとlong、署名されたままになります。ただし、intにキャストバックすると、正しい値にオーバーフローします。

于 2012-08-17T12:12:00.473 に答える
51

数値が負であるため、オーバーフローします。

これを試してみてください。

int n = (int) Long.parseLong("ffff8000", 16);
于 2012-08-17T12:12:51.487 に答える
30
  • int16進数へ:

    Integer.toHexString(intValue);
    
  • 16進数int

    Integer.valueOf(hexString, 16).intValue();
    

long代わりに使用することもできます(値が境界intに合わない場合):int

  • 16進数long

    Long.valueOf(hexString, 16).longValue()
    
  • long16進数に

    Long.toHexString(longValue)
    
于 2012-08-17T12:10:26.963 に答える
11

Integer.parseUnsignedIntJava 8にはメソッドがあり、Long.parseUnsignedLongそれはあなたが望んでいたことを具体的に行うことに言及する価値があります:

Integer.parseUnsignedInt("ffff8000",16) == -32768

16 進文字列から符号付き整数を解析するため、名前は少しわかりにくいですが、機能します。

于 2016-03-04T19:09:38.227 に答える
7

BigInteger クラスを使用してみてください。動作します。

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());
于 2012-08-17T12:16:02.057 に答える
3

Java の parseInt メソッドは、実際には "false" hex を食べるコードの束です: -32768 を変換したい場合は、絶対値を 16 進数に変換し、文字列の前に「-」を追加する必要があります。

Integer.java ファイルのサンプルがあります:

public static int parseInt(String s, int radix)

説明は非常に明確です:

* 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
于 2012-08-17T12:16:15.807 に答える
2

以下のコードは動作します:

int a=-32768;
String a1=Integer.toHexString(a);
int parsedResult=(int)Long.parseLong(a1,16);
System.out.println("Parsed Value is " +parsedResult);
于 2019-02-23T15:13:01.423 に答える
1

へへへ、好奇心旺盛。これはいわば「意図的なバグ」だと思います。

根本的な理由は、Integer クラスの記述方法にあります。基本的に、parseInt は正の数に対して「最適化」されています。文字列を解析すると、結果が累積的に構築されますが、否定されます。次に、最終結果の符号を反転します。

例:

66 = 0x42

次のように解析されます:

4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)

-64 - 2 = -66 (hex 2 parsed)

return -66 * (-1) = 66

それでは、あなたの例 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.

編集 (追加): parseInt() が -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE に対して「一貫して」機能するためには、累積結果。整数範囲の最大端から開始し、そこから下に向かって続きます。なぜ彼らがこれをしなかったのか、Josh Bloch か、最初に実装した人に尋ねなければなりません。単なる最適化かもしれません。

でも、

Hex=Integer.toHexString(Integer.MAX_VALUE);
System.out.println(Hex);
System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));

この理由だけで、うまく機能します。Integer のソースには、このコメントがあります。

// Accumulating negatively avoids surprises near MAX_VALUE
于 2012-08-17T13:01:20.913 に答える