「二進数を計算してみよう」の解答例

二進数は情報系の学問やコンピュータを学ぶ上で必要な知識です。2進数を扱うプログラムも書いてしっかり理解を深めましょう。

この記事はC言語演習問題集の問題の回答です。まだ問題読んでないという方は下記記事の「二進数を計算してみよう」をぜひ見てから読んでください。

C言語練習問題のアイキャッチC言語応用問題集

解答例


#include <stdio.h>

int main(void){
  int x;
  unsigned long b;
  int m;
  int i;
  int j;
  int a;
  int input;

  printf("二進数に変換する数字は?:");
  scanf("%d", &x);

  if(x > 512 && x < 0){
    printf("対応していない入力です\n");
    return -1;
  }

  input = x;

  b = 0;
  i = 0;
  while(x > 0){
    m = 1;
    for(j = 0; j < i; j++){
      m = m * 2;
    }
    if(x & m){
      a = 1;
      for(j = 0; j < i; j++){
        a = a * 10;
      }
      b += a;
      x -= m;
    }
    i++;
  }
  printf("%dを二進数で表すと%luです\n", input, b);

  return 0;
}

表示例

スポンサーリンク

解説

2進数の基礎

まず2進数の基礎を復習しましょう。

2進数とは2を基数とした数値であり、数を1と0のみで表現します。

我々が馴染みあるのは10進数で、10を基数とした数値であり、これは0から9の10種類の数で表現されます。

他にも8進数や16進数などが存在し、それぞれ8を基数・16を基数とした数値となります。

基数変換

数値を基数の各冪乗数の数値単位で分解してみましょう。

これだけだと何を言ってるか分かりにくいので10進数の157の実例を用いて説明します。

157は100が1つ、10が5つ、1が7つ足し合わされた数字として考えることができます。

100は10の2乗、10は10の1乗、1は10の0乗であり、それぞれが基数の冪乗数となっています。

これを数式で表すと、

となります。

まるで囲った部分を左から並べると157です。元が10進数の157なので同じ結果になって何をやっているか分かりにくいかもしれませんが、他の進数に変換する場合も同じ考え方で行うことが可能です。

2進数に変換することとを考えましょう。まず基数の各冪乗数単位に分解してみましょう。

157は128が1つ、64が0つ、32が0つ、16が1つ、8が1つ、4が1つ、2が0つ、1が1つ足し合わされた値として考えることができます。

128から1は全て2進数の基数である2の冪乗数になっています。

これを数式で表すと、

となり、まるで囲った部分を左から並べると、10011101となり、10進数の157を2進数に変換した結果になります。

つまり10進数から各進数に変換するためには、各基数の冪乗数がいくつその値に含まれているかを考えれば良いのです。

解答例プログラムの説明

この解答例はこの考え方に従って10進数を2進数に変換するプログラムになっています。

まずこの部分で2の冪乗数を求めています。iは何乗するかを示す値であり、while文で繰り返すたびに1増やしています。

    for(j = 0; j < i; j++){
      m = m * 2;
    }

これにより2のi乗の値が求まります。

次は条件判断により、入力された10進数に2のi乗が含まれているかどうかを判断しています。

    if(x & m){

&は左辺が右辺と同じビットが立っているかを判断する演算子です。

2のi乗は必ず1つだけビットが立っている状態であり、&結果が1であれば入力された数字も同じビットが立っている状態であり、2のi乗を含んでいる数字と判断できます。

逆に結果が0であれば、入力された数字に2のi乗が含まれていない事になります。

この判断文により2のi乗が含まれていると判断した場合は、下記で結果となる2進数を格納するbに10のi乗を足し合わせます。

      for(j = 0; j < i; j++){
        a = a * 10;
      }
      b += a;

10のi乗を足し合わせているのは単に便宜上の話です。実際やろうとしているのは2進数の右からi桁目を1にセットしていると考えてもらって良いです。

さらに含まれていた2のi乗の値を入力された数字から減算しています。

      x -= m;

最終的に入力された数字が0になれば、2の基数へ分解し終わったと考えることができますので、while文を終了し、結果を出力しています。

独り言

割と簡単にプログラムは作れました。ですが、2進数の数を変数に格納しようとしたのが思ったよりよくなかったですね。unsinged long型でもすぐに桁あふれが発生してしまいました。変数に格納するのではなく、随時1か0をprintfするプログラムの方がやっぱりいいですね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です