HOWTO · Java

Java で 10 進数から 2 進数への変換

このチュートリアルでは、Java で 10 進数を 2 進数に変換する方法を示します。

このページの内容

通常の整数から2進数文字列への変換には、JavaのInteger.toBinaryString(int)を使えます。次の例では整数50を変換します。

Javaで10進整数を2進数に変換する

最も簡潔に変換するにはInteger.toBinaryStringを使います。次の自己完結したプログラムは整数50を変換し、2進数の各桁を出力します。

このセクションのコードと表示されるラベルや出力は英語のままです。

public class DecimalToBinary {
  public static void main(String[] args) {
    int decimal = 50;
    String binary = Integer.toBinaryString(decimal);
    System.out.println(binary);
  }
}

手順を理解するには2で繰り返し割る方法が役立ち、表示するビット数を指定したい場合はビット演算による抽出が便利です。負の値の表し方は手法によって異なるため、Javaの符号付きintのビットパターンが必要なのか、符号と絶対値を使った文字列が必要なのかに応じて選びましょう。標準メソッドは先頭のゼロを付けずに文字列を返します。0以上のintではこれが最小桁数の表現となり、10進数の50は110010になります。負のintの場合、Javaは32ビットの2の補数表現を返します。つまり、結果は負号に続く絶対値ではなく、32桁の2進数になります。0以上の値を一定の幅で表示するには、文字列の左側をゼロで埋める方法などを使います。ゼロ埋めは表示形式を変えるだけで、整数の値は変わりません。コードと出力のフェンス内は変更していないため、そこに含まれるプロンプトやラベルは英語のままです。

2で繰り返し割って10進整数を手動で変換する

自分で桁を作るには、0以上の値を2で繰り返し割り、そのたびに余りを記録します。余りは最下位桁から最上位桁の順に得られるため、文字列として表示する前に逆順にします。この例では0を明示的に処理し、負の値は負号の後に絶対値の2進数を続けて表します。絶対値を求める前にlongへ変換するため、Integer.MIN_VALUEも安全に扱えます。

このセクションのコードと表示されるラベルや出力は英語のままです。

public class RepeatedDivision {
  static String toBinary(int value) {
    if (value == 0) {
      return "0";
    }

    boolean negative = value < 0;
    long remaining = Math.abs((long) value);
    StringBuilder digits = new StringBuilder();

    while (remaining > 0) {
      digits.append(remaining % 2);
      remaining /= 2;
    }

    digits.reverse();
    return negative ? "-" + digits : digits.toString();
  }

  public static void main(String[] args) {
    System.out.println(toBinary(33));
    System.out.println(toBinary(-33));
    System.out.println(toBinary(0));
  }
}

この手動の方法では、負の入力を符号と絶対値で表します。そのため、負の値に対する結果はInteger.toBinaryStringと同じ形式ではありません。StringBuilderは桁数に応じて伸びるため、根拠のない固定サイズの配列を使わずに済みます。Java標準の整数変換で十分な場合は、標準ライブラリのメソッドを使いましょう。コードと出力のフェンス内は変更していないため、プロンプトやラベルは英語のままです。

ビット演算子で整数のビットを取り出す

ビットを取り出す方法では、表示するビットパターンの幅を指定できます。その幅で最上位のビットから始め、シフトして最下位の位置に移動し、1とのマスク演算で値を取り出します。この例では幅を8ビット、値を13にしています。

このセクションのコードと表示されるラベルや出力は英語のままです。

public class FixedWidthBits {
  public static void main(String[] args) {
    int value = 13;
    int width = 8;
    StringBuilder bits = new StringBuilder();

    for (int bit = width - 1; bit >= 0; bit--) {
      bits.append((value >>> bit) & 1);
    }

    System.out.println(bits);
  }
}

符号なし右シフト演算子(>>>)とマスクによって、各ビットを個別に取り出せます。幅を固定すると、Integer.toBinaryStringとは異なり、表示結果の先頭にあるゼロも保持されます。表示したい表現に合う幅を選んでください。このループが表示するのは下位8ビットなので、それより大きい値や負の値はその幅に切り詰められます。intの全ビットを表示するには、幅にInteger.SIZE(32)を指定します。これは表現方法の選択であり、速度に関する主張ではありません。コードと出力のフェンス内は変更していないため、プロンプトやラベルは英語のままです。

なぜMath.pow()で2進数を組み立てないのか?

Math.pow()はdoubleを返します。また、2進数の各桁を整数の10進位として扱う方法には問題があります。たとえば、remainder * Math.pow(10, position)を加算すると、文字がたまたま0と1で構成された10進数が作られますが、2進数の値が格納されるわけではありません。桁数が増えると、その10進整数はintの範囲を超える可能性があります。また、任意の桁数の数字を組み立てる方法として、浮動小数点数のべき乗に頼るのも適切ではありません。数値では先頭のゼロも保持できません。整数には、先頭にゼロを何文字付けるつもりだったかという情報がないためです。

2進数の各桁は、代わりにStringとして扱いましょう。Java標準の整数表現にはInteger.toBinaryStringを使い、変換を学んだり独自に調整したりするには繰り返し除算を使います。特定の幅が必要な場合は、幅を指定したビット抽出を選べます。これらの方法なら、負の値の扱いと先頭のゼロの表示を明確にできます。コード例と出力は変更していないため、フェンス内のプロンプトやラベルは英語のままです。