Integer.parseIntを使用した32ビットのバイナリ文字列の変換に失敗する

2012年01月17日に質問されました。  ·  閲覧回数 14.7k回  ·  ソース

Aliens picture
2012年01月17日

コードのこの部分が失敗するのはなぜですか。

Integer.parseInt("11000000000000000000000000000000",2);

Exception in thread "main" java.lang.NumberFormatException: For input string: "11000000000000000000000000000000"

私が理解している限り、整数は32ビット値です。 上のコードの0と1の数は32です。31がある場合、コードは機能します。 どうしてこんなことに?

回答

millimoose picture
2012年01月17日
17

符号付き整数として格納するために33ビットを必要とする数値を解析しようとするため、コードは失敗します。

符号付きintは、2の補数表現の32ビット値です。最初のビットは数値の符号を示し、残りの31ビットは数値の値を示します。 (-ish。)Javaは符号付き整数のみをサポートし、 parseInt()とその仲間は、2の補数ビットパターンを解析することは想定されていません。したがって、 1または(おそらく暗黙の) 0を解釈します。右から32番目の- (または+ )と、それに続く数値の絶対値です。

この文脈では、それはリードが、あなたが記述する行動を期待するという誤った直感です:あなたはの最初の数字を期待し、ベース2(または多分他の一般的に使用される電力の-2塩基)以外の任意の他の塩基を解析した場合記号に影響を与える入力? 明らかに、あなたはそうしません。 たとえば、 parseInt("2147483648") -2147483648が設計上-2147483648返すようにすることは、PHPレベルの狂気になります。

特別なケーシングの2つのベースの力も奇妙に感じます。 たとえば、この回答のように、ビットパターンを処理するための別のアプローチを使用することをお勧めし

Mike Christensen picture
2012年01月17日
4

ドキュメントによると、整数の最大値は2^31-1です。 これは、バイナリでは次のとおりです。

1111111111111111111111111111111

つまり、31個の1が連続しています。

Evgeniy Dorofeev picture
2013年08月29日
2

これは、Integer.parseIntの場合、「11000000000000000000000000000000」は-1073741824の2の補数表現ではなく、int値の範囲-2147483648〜2147483647に適合しない正の値3221225472であるためです。ただし、BigIntegerを使用して2の補数のバイナリ文字列表現を解析できます。

int i = new BigInteger("11000000000000000000000000000000", 2).intValue()

これにより、予想される-1073741824の結果が得られます

user949300 picture
2012年01月17日
0

文字列「11 ..... lots of zeros」は負の整数の正当なバイナリ表現ですが、Integer.parseInt()は失敗します。 これはバグだと思います。

少し妥当性を追加すると、この投稿を読み直すと衒学的すぎるように聞こえるので、これがバグであるかどうかにかかわらず、Oracleはおそらくあまり気にしないことを理解しています。 :-)

あなたが試すことができます:

   long avoidOverflows = Long.parseLong("11000000000000000000000000000000",2);
   int thisShouldBeANegativeNumber = (int)avoidOverflows);
   System.out.println(avoidOverflows + " -> " + thisShouldBeANegativeNumber);

見るべき
3221225472-> -1073741824

テキストとして保存する方法によっては、Colorsを使用してこれを行う必要がある場合があります。

ところで、16進表現を解析していて、「88888888」のような負の数を解析している場合、正確なことが起こる可能性があります。 Long.parseLong()を使用してから変換する必要があります。