LoginSignup
2
1

More than 5 years have passed since last update.

【Java】Integer.parseInt()で負の2進数を扱う場合の考慮

Last updated at Posted at 2019-03-03

動作環境

Java11

内容

大した内容じゃないのでいきなり本題に入ります。

Javaでは、負の数は内部的には2の補数で表現されています。Integer.toBinaryString()を使うと、内部的な表現の文字列を得ることができます。

2の補数は、2進数の場合は全てのビットを反転させてから1を足した数になります。10進数の15は2進数では1111なので、10進数の-15は下記の値になります。

System.out.println(Integer.toBinaryString(-15))  // 11111111111111111111111111110001

しかし、Integer.parseInt()にこの値を渡すとエラーとなってしまいます。

Integer.parseInt(Integer.toBinaryString(-15), 2)
//  例外java.lang.NumberFormatException: For input string: "11111111111111111111111111110001"
//        at NumberFormatException.forInputString (NumberFormatException.java:65)
//        at Integer.parseInt (Integer.java:652)
//        at (#9:1)

どうやらInteger.parseInt()には、内部的な2の補数表現の値ではなく、正の2進数に負の符号を付けた形で渡す必要があるようです。

System.out.println(Integer.parseInt("-1111", 2))  // -15

以上です。

2019/3/4 追記
コメントにていくつかご指摘いただきました。

整数引数の文字列表現を、基数2の符号なし整数として返します。
符号なしint値は、引数が負の数の場合は、引数に2^32を加算した値になります。

(そのままコピペすると232となる箇所を2^32に修正しています)

引数が負の値の場合は内部的な2の補数表現を返すと記述していましたが、公式ドキュメントでは上記のような記述になっているようです。
ただ、結果的には同じことになります。Rubyを使って検証しました。(Javaだとオーバーフローになったりしていろいろ面倒なため)

まずJavaのInteger.toBinaryString()の戻り値

System.out.println(Integer.toBinaryString(-15));  // 11111111111111111111111111110001

引数の値(-15)に2^32を加算した値の二進数表現

n = -15 + 2 ** 32
puts(n.to_s(2))   # 11111111111111111111111111110001

どちらも11111111111111111111111111110001になることが確認できました。

また、この内部的な二進数をそのままパースできるInteger.parseUnsignedInt()というメソッドがあるようです。

System.out.println(Integer.parseUnsignedInt(Integer.toBinaryString(-15), 2));  // -15

ご指摘ありがとうございました。(そもそも公式ドキュメントを読めという話ですね…)

2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1