C＃で全進数を相互に変換するプログラムを作成してみた

#初めに
・専門学校に通う1年生がC#の勉強をするために作ったプログラムです。誤字、脱字や『もっとこうしたほうがいいよ！』などあればご指導いただけるとありがたいです。
・下記のようにConvertクラスのToInt32メソッドとToStringメソッドを使えば一発で変換できますが、今回はあくまで勉強として作成しているので使用しておりません。
>**例えば**
16進数のffffを10進数表すと65535に変換できます。
ToInt32メソッドを使用して、メッセージで表示するプログラムです。

>```Csharp:test
string n="ffff";
int num16 = Convert.ToInt32(n, 16);
MessageBox.Show(num16.ToString());
```
***
>逆に10進数の65535を16進数のffffに変換したい場合、ToStringメソッドを使用してメッセージで表示します。

>```Csharp:test
int num = 65535;
string str = Convert.ToString(num,16);
MessageBox.Show(str);
```

・最後に[Twitter](https://twitter.com/hirotaka_0426)の方も最近、作ったのでフォローお願いします！

#作ったきっかけ
きっかけは**2つ**あります。
>**・1つ目**
担任の先生にアルゴリズムを理解したければ、プログラムを作り続け、どうなってるのかを理解するしかないと言われたため。
**・2つ目**
C#を担当している先生が進数を変換するプログラムが欲しいと言っていたため。
（そんなようなこと言ってた気がする）

#進数とは
まず、進数とは、あらかじめ定められたN 種類の記号（数字）を列べることによって数を表す方法です。
[Wikipedia](https://ja.wikipedia.org/wiki/%E9%80%B2%E6%95%B0)参照
>**難しいので自分なりにまとめました。**

>まずN進数のNとはN種類の英数字を使用すると思ってください。

>・2進数の場合は0と1の2種類
・8進数の場合は0～7の8種類
・10進数の場合は0～9の10種類
・16進数の場合は0～9の数字とAからFの英字で16種類
を使用します。

#変換
私が作ったプログラムでは、主に**2種類**の変換方法を使用しています。
2種類とも、人間が得意とする10進数に関わりがあります。
>**・1種類目**
初めに2進数、8進数、16進数を10進数に変換する方法です。
**・2種類目**
次に逆のパターンです。
10進数を2進数、8進数、16進数と、それぞれの進数に変換する方法です。
>>☆この2つの変換方法を使えば、それぞれの進数がスタートでもゴールでも変換することができます。

>**例えば**
2進数から8進数にしたい場合、実際には変換する方法はあります。
![スクリーンショット 2021-12-28 162520.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342342/db1e1e15-7845-400a-7ae4-7079e48c4894.png)
>この画像のように3桁ごとに区切り、重みを位ごとに足していくことによって表現できますが、今回作ったプログラムでは、一度10進数を経由して表現しています。
>>・2進数から10進数にした後に、10進数から8進数の順で変換しています。
>では、実際のコードを紹介します。

#実際のコード
・全体的なコード

```Csharp:main
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace sinsuuhenkan
{
    public partial class Form1 : Form
    {
        string deta = "";//入力される進数
        string a = "0123456789abcdef";//16進数用の変換配列
        //10進数に変換するメソッド
        public string henkan(string deta, int basu)
        {
            //変数型定義
            int ans = 0;
            int i = 1, j, len;
            len = deta.Length;//lenに文字数を代入
            //lenが0より大きい時
            while (len > 0)
            {
                //10進数に変換
                j = a.IndexOf(deta[len - 1]);//16進数用に文字変換
                ans += j * i;
                i = i * basu;
                len = len - 1;
            }
            this.deta = ans.ToString();//int型をstring型に変換
            return this.deta;//返却値
        }
        //10進数から変換するメソッド
        public string reversehenkan(string deta, int basu)
        {
            //変数型定義
            int redeta, j,len;
            string ans="",answer="";
            redeta = int.Parse(deta);//detaをint型に変換
            //redetaが0じゃない時
            while (redeta != 0)
            {
                //10進数から変換
                j = redeta % basu;
                ans += a.Substring(j,1);
                redeta = redeta / basu;
            }
            len = ans.Length;//lenに文字数を代入
            //文字列を出力を逆にする
            //iの初期値をlen-1にiが0以上の時
            for (int i = len-1; i >=0; i--)
            {
                answer += ans.Substring(i,1);
            }
            this.deta = answer.ToString();//int型をstring型に変換
            return this.deta;//返却値
    }
}
```

#説明
>**見にくいので細かく分解して説明していきましょう。**
・最初に

>```Csharp:From1
        string deta = "";//入力される進数
        string a = "0123456789abcdef";//16進数用の変換配列
```

>が自分で作ったメソッドの外(Form1)で定義していることを、頭の片隅に置いといてください。
配列aは16進数の英字を数字に変えるために使います。
>>次にそれぞれの**2種類**のメソッドの説明をしていきます。
###まずhenkanというメソッドについてです。

>>```Csharp:henkan
        //10進数に変換するメソッド
        public string henkan(string deta, int basu)
        {
            //変数型定義
            int ans = 0;
            int i = 1, j, len;
            len = deta.Length;//lenに文字数を代入
            //lenが0より大きい時
            while (len > 0)
            {
                //10進数に変換
                j = a.IndexOf(deta[len - 1]);//16進数用に文字変換
                ans += j * i;
                i = i * basu;
                len = len - 1;
            }
            this.deta = ans.ToString();//int型をstring型に変換
            return this.deta;//返却値
        }
```
これはそれぞれの進数を10進数に変換させるメソッドです。
例えばdetaに**2進数の1011**を持ってるとき、メソッドを使うときにhenkan(deta,2)というように引数を渡します。すると結果は**10進数の11**になります。
この時やりたい事はおおよそ**４つ**です。
***
>>**１．**まず16進数があるならAを10、Bを11のように**英字を数字**にしたい。
　　配列aと[IndexOf](https://itsakura.com/csharp-indexof)を使って要素数を取得しint型に変換した後、**j**に代入します。
　　(16進数じゃない時も同じ数字が返ってくるので使用可能です。)
　　**※**[IndexOf](https://itsakura.com/csharp-indexof)の個人的にわかりやすいと思うサイトをリンクさせました。
**２．**まず一の位から処理していきます。取得した**j**と**i**をかけて以前の**ans**に足して**ans**に代入するようにします。
　　**※**ans+=〇とはans=ans+〇と同じ意味です。
**３．**この時の**i**とは第２引数で受け取った数字のべき乗です。
　　つまり2進数の時で、一の位なら２の０乗、十の位なら２の１乗です。
**４．**そして**len**から１引いて次の位に移ります。

##解説
>もう少し深く見ていきましょう、実際に値を入れていきます。
先生も実際にやってみた方が分かりやすいと言っていました。笑
>>先ほどの**2進数の1011**で検証してみましょう。
この時のメソッドは、henkan(1011,2);と書きます。
>>>・まずメソッドに入った時に**lenは4**になります。
・条件が真なのでループに入って**j**の代入処理をします。
①**len-1**からint型に変換します。
　-1をしている理由は配列の始まりが0からだからです。
　☆例：**j**には一の位の1が代入されます。
②次に**ans+=j*i**をします。
　これは**j**に2進数のべき乗していった値を**ans**に代入しています。
　☆例：**ans**には1×1で**1**が代入されます。
③**i**はべき乗をかけるので次の**i=i+base**の処理をしていきます。
　**besu**には第2引数が与えられます。
　ここの値は**n**進数を10進数に変えるときの、**n**を第2引数として書きます。
　☆例：**i**には1×2で**2**が代入されます。
④最後に十の位に移りたいため**len=len-1**をします。
　☆例：**len**は4-1で**3**が代入されます。
・条件が真のとき①に戻り、繰り返し処理していきます。
　☆例：
　　　　![スクリーンショット 2022-01-06 143556.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342342/b42986fa-16db-c137-46fc-8421b76d11ed.png)
・最後の**ans**が**11**なので2進数の1011を10進数にすると**11**になるということがわかります。

###次にreversehenkanのメソッドを見ていきます。
>```Csharp:reversehenkan
        //10進数から変換するメソッド
        public string reversehenkan(string deta, int basu)
        {
            //変数型定義
            int redeta, j,len;
            string ans="",answer="";
            redeta = int.Parse(deta);//detaをint型に変換
            //redetaが0じゃない時
            while (redeta != 0)
            {
                //10進数から変換
                j = redeta % basu;
                ans += a.Substring(j,1);
                redeta = redeta / basu;
            }
            len = ans.Length;//lenに文字数を代入
            //文字列を出力を逆にする
            //iの初期値をlen-1にiが0以上の時
            for (int i = len-1; i >=0; i--)
            {
                answer += ans.Substring(i,1);
            }
            this.deta = answer.ToString();//int型をstring型に変換
            return this.deta;//返却値
        }
```
これは10進数を全進数にするためのメソッドです。
例えばdetaに**10進数の11**を持ってるとき、メソッドを使うときにreversehenkan(deta,2)というように引数を渡します。すると結果は**2進数の1011**になります。
説明していきます。
>>**１．**まず**deta**をint型に変換します。
　　数値にした**redeta**を**basu**(変換先の進数)で割り、余りを**j**に代入します。
**２．**このままでは16進数にするとき、数字の10や11が**英字**になりません。
　　そこでaの配列と[Substring](https://itsakura.com/csharp-substring)を使って、文字に変換しつつ**ans**に代入します。
　　**※**Substringは簡単に言うと、配列の中身を取り出すメソッドです。
　　　わかりやすいと思うサイトをリンクさせました。
**３．**最後に**redeta**を**basu**で割り**redeta**に代入します。
**４．**このループだと出力したときに**文字列が逆**になります。
　　なので、次のループで配置を左右反転していきます。

##解説
>実際に値を入れて見てみましょう。
今回、**10進数の11**を**2進数の1011**に変換していきます。
メソッドはreversehenkan(11,2)と書きます。
>>・11をint型に変換します。
**※**見た目ではほとんど変わりないですが、パソコンでは**文字の１**と**数字の１**は[ASCIIコード](http://www3.nit.ac.jp/~tamura/ex2/ascii.html)といい全くの別物です。
![スクリーンショット 2022-01-06 233717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342342/fc8f8650-7227-45f5-ea0a-549b18731ca8.png)
・まず上の画像のように処理したいというイメージを持っといてください。
①**j=redeta%basu**とは、まず％で余りを取り出せます。
　☆例：つまり、上の画像の通り**11÷2＝5余り1**で**1**を**j**に代入するということになります。
②これだけでは16進数が来た時に数字を英字に変換できません。
　なのでSubstringを使います。
　※今回16進数はないですが、ここで**int型**から**string型**に変換しているので覚えといてください。
③このままだとループしても**redeta**がそのままです。
　ですので最後に**redeta**を**basu**で割ります。
　☆例：**basu**は第二引数のことなので**11÷2＝5余り1**でredetaは**5**になります。
・条件が真のとき①に戻り、繰り返し処理していきます。
　☆例：
　　　　![スクリーンショット 2022-01-09 150119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342342/557223d9-5a8b-c191-f316-6b197253522e.png)
・**redeta**が**0**になった時点でループから抜けますが、今回はこれで終わりではありません。よく見てみると、出力したい値は**1011**ですが、ここのansの値は**1101**です。なので次のループで並び替えをする必要があります。
④**ans**の後ろの値から順に**answer**に格納して例のように並べ替えして、
　☆例：ans　　　**1101**　↓
　　　　answer　 **1011**
　となります。　
・これで**10進数の11**が**2進数の1011**になりました。

＃結論
>・これで全進数を相互変換できるプログラムができました。
・デザインは、、、
![スクリーンショット 2022-01-10 195430.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342342/e0a5439e-97a5-cdb1-1099-681b719c635b.png)
こんな感じにしてみました。

>後から気づいたんですが、ラジオボタンなどを使えばもっとかっこよく、効率よくできたのかなと思います。これも経験ですかね、笑

#まとめと今後
・今回はC#で全進数を相互に変換するプログラムを作ってみました。今は誰もが作れるようなプログラムを作ったりし、応用的なものは作れていませんが、今後はこれを応用したプログラムを作ろうと考えています。
・例えば変換過程をtextで表示し、初心者にわかりやすいように改良したり、小数点も変換できるようにしようと考えています。
***
・ここまで見ていただきありがとうございました。初めてQiitaを書き、文章を分かりやすく書くのは難しいなと思いました。4年間で上手く書けるようになれればなと思います。笑