10進数→２進数変換は難しすぎて筆算じゃないとできないよ！！

#２進数変換は高校数学で習った
某国立大学情報学部に通う僕は、最近情報科学系の実験で２進数をよく使うようになってきました。
実験では、FPGAと呼ばれる集積回路を積んだ基板のようなボードのようなものに、設計した論理回路を送り込んで「１たす１ができたぞおおお」みたいな小学生のような大学生のようなことをしています。
意味わからないですよね、符号つき２進数は正の数と正の数を足して負の数になったりするのですから面白い。
しかしながら20年間慣れ親しんできたのは10進数ですし、物事は基本的に10進数で考えます。僕の脳ミソは仮面ライダーゼロワンではありません。（実際の仮面ライダーは見ていないので知りません）
流石に、５〜６桁くらいまでは暗算でも10進数⇔2進数の変換はできますが、それ以上の桁数になると、計算機を使うか手計算をします。
今回の記事では、最近古いパソコンを漁っていたら昔作った10進数→2進数変換プログラムが発掘されたので、ご紹介しようと思います。

#まずはプログラムを
今回はjavaで書きました。
大学１年生の頃はjavaしか触れなかったので、この世には日本語と英語とjavaしか言語が存在しないと信じていました。
まだまだプログラミングに慣れていない時期のものなので、設計やコーディングについて、いろいろ物申したいこともたくさんあるかと思いますが、可愛い孫の成長を見ているかのような温かい目で見ていただけたら幸いです。何も手直しせずそのまま貼り付けます。

```java:binary_change.java
import java.util.Stack;
import java.util.*;

class binary_change{
  public static void main(String args[]){
    Scanner sc = new Scanner(System.in);

    System.out.println("Input number.");
    int inputnum = sc.nextInt();

    transrate(inputnum);
  }

  public static void transrate(int num){
    final int numnumnum = num;
    Stack stack = new Stack();
    int stacksize = 0;
    stacksize = stack.size();
    int numnum = 1;
    do{
      numnum = numnum * 2;
      stacksize ++;
    }while(numnum < num);

    System.out.println("stacksize is " + stacksize);
    int nextnum1;
    int nextnum2;
    int surplus;
    int surplus1;
    int surplus2;

    surplus = num % 2;
    System.out.println("2 )" + num + "..." + surplus);
    System.out.println("----------");
    stack.push(surplus);
    do{
      nextnum1 = num / 2;
      surplus1 = num % 2;
      if (nextnum1 == 1) {
        break;
      }

      num = nextnum1;

      nextnum2 = num / 2;
      surplus2 = num % 2;


      System.out.println("2 )" + nextnum1 + "..." + surplus2);
      System.out.println("----------");
      stack.push(surplus2);
      if (nextnum2 == 1) {
        System.out.println("2 )" + nextnum2);
        stack.push(nextnum2);
        break;
      }

    }while (true);
    System.out.println("Deciminal number ---> Binary number");
    System.out.print(numnumnum + " ---> ");
    for (int i = 0; i < stacksize; i ++) {
      System.out.print(stack.pop());
    }
    System.out.println(" ");
  }
}
```

普段全くjavaを書かない僕でも、３年間の成長でこのコードかうんちなのが理解できます。
でもよくよく考えると、昔はこのようなツール系のプログラムをガムシャラに書いていたなぁとしみじみ思います。
こういう積み重ねは、本当に大切だと思います。

では、どのような挙動になるのか、実行してみます。

```
takeshitatakushuunoMacBook-ea:Desktop hirosugutakeshita$ java binary_change
Input number.
810
stacksize is 10
2 )810...0
----------
2 )405...1
----------
2 )202...0
----------
2 )101...1
----------
2 )50...0
----------
2 )25...1
----------
2 )12...0
----------
2 )6...0
----------
2 )3...1
----------
2 )1
Deciminal number ---> Binary number
810 ---> 1100101010 
takeshitatakushuunoMacBook-ea:Desktop hirosugutakeshita$ 
```
#プログラムの説明
結果を見ていただいた通り、こいつは計算機のくせに筆算で変換を計算します。
メソッドは２つ、メインと変換部ですね。ほとんど全ての計算は`transrate()`の中でやってます。メインメソッドは値をとって引数を与えているだけです。

`transrate()`の中身も軽く説明します。
もはや見たままですが、本当に手書き筆算みたいなことしてますね。
２で割って、商と余りに分けて、余りはスタックに積んでます。商は次の計算用に変数に保存しておきます。
あとは筆算に見えるように商と余りをいい感じのところに出力して、最後商が１になるまで続けています。
2進数変換の筆算では（他の進数変換でもそうですが）余りの数（今回は0か１）をしたから読むのがポイントでしたね。数学の教科書にはそう書いてあった気がします。したがって使用するデータ構造にスタックを選択しているのは一つの工夫だと思います。スタックに積んだ順と逆順に値が出ていくのですから、筆算の余りの部分をしたから読むのと同じことになります。

![スタック .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/ed555326-6472-be42-8c0f-b1a698cd9c1b.png)


#思うこと
こういうのを”アルゴリズム”とは言わない気もしますが、おそらく探せば存在するであろう変換計算ライブラリを使わずに2進数へ変換しているので、まあまあ面白いんじゃないかと思います。
このツールは、筆算を使って2進数へ変換する課題が100問くらい出された時にぜひ活用してください。

昔のプログラムを見るのもたまには面白いなと思います。自分の成長が感じられると共に、こんな書き方をしたら読みにくいじゃないか、みたいな発見もあります。たまにはこういうのもいいなあと思いました。（激ゆる）