動作環境
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
ご指摘ありがとうございました。(そもそも公式ドキュメントを読めという話ですね…)