LoginSignup
2
3

More than 1 year has passed since last update.

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

Posted at

初めに

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

例えば
16進数のffffを10進数表すと65535に変換できます。
ToInt32メソッドを使用して、メッセージで表示するプログラムです。

test
string n="ffff";
int num16 = Convert.ToInt32(n, 16);
MessageBox.Show(num16.ToString());

逆に10進数の65535を16進数のffffに変換したい場合、ToStringメソッドを使用してメッセージで表示します。

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

・最後にTwitterの方も最近、作ったのでフォローお願いします!

作ったきっかけ

きっかけは2つあります。

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

進数とは

まず、進数とは、あらかじめ定められたN 種類の記号(数字)を列べることによって数を表す方法です。
Wikipedia参照

難しいので自分なりにまとめました。

まず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
この画像のように3桁ごとに区切り、重みを位ごとに足していくことによって表現できますが、今回作ったプログラムでは、一度10進数を経由して表現しています。

・2進数から10進数にした後に、10進数から8進数の順で変換しています。
では、実際のコードを紹介します。

実際のコード

・全体的なコード

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;//返却値
    }
}

説明

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

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

が自分で作ったメソッドの外(Form1)で定義していることを、頭の片隅に置いといてください。
配列aは16進数の英字を数字に変えるために使います。

次にそれぞれの2種類のメソッドの説明をしていきます。

まずhenkanというメソッドについてです。

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になります。
この時やりたい事はおおよそ4つです。


1.まず16進数があるならAを10、Bを11のように英字を数字にしたい。
  配列aとIndexOfを使って要素数を取得しint型に変換した後、jに代入します。
  (16進数じゃない時も同じ数字が返ってくるので使用可能です。)
  IndexOfの個人的にわかりやすいと思うサイトをリンクさせました。
2.まず一の位から処理していきます。取得したjiをかけて以前のansに足してansに代入するようにします。
  ans+=〇とはans=ans+〇と同じ意味です。
3.この時のiとは第2引数で受け取った数字のべき乗です。
  つまり2進数の時で、一の位なら2の0乗、十の位なら2の1乗です。
4.そしてlenから1引いて次の位に移ります。

解説

もう少し深く見ていきましょう、実際に値を入れていきます。
先生も実際にやってみた方が分かりやすいと言っていました。笑

先ほどの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
・最後のans11なので2進数の1011を10進数にすると11になるということがわかります。

次にreversehenkanのメソッドを見ていきます。

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になります。
説明していきます。

1.まずdetaをint型に変換します。
  数値にしたredetabasu(変換先の進数)で割り、余りをjに代入します。
2.このままでは16進数にするとき、数字の10や11が英字になりません。
  そこでaの配列とSubstringを使って、文字に変換しつつansに代入します。
  Substringは簡単に言うと、配列の中身を取り出すメソッドです。
   わかりやすいと思うサイトをリンクさせました。
3.最後にredetabasuで割りredetaに代入します。
4.このループだと出力したときに文字列が逆になります。
  なので、次のループで配置を左右反転していきます。

解説

実際に値を入れて見てみましょう。
今回、10進数の112進数の1011に変換していきます。
メソッドはreversehenkan(11,2)と書きます。

・11をint型に変換します。
見た目ではほとんど変わりないですが、パソコンでは文字の1数字の1ASCIIコードといい全くの別物です。
スクリーンショット 2022-01-06 233717.png
・まず上の画像のように処理したいというイメージを持っといてください。
j=redeta%basuとは、まず%で余りを取り出せます。
 ☆例:つまり、上の画像の通り11÷2=5余り11jに代入するということになります。
②これだけでは16進数が来た時に数字を英字に変換できません。
 なのでSubstringを使います。
 ※今回16進数はないですが、ここでint型からstring型に変換しているので覚えといてください。
③このままだとループしてもredetaがそのままです。
 ですので最後にredetabasuで割ります。
 ☆例:basuは第二引数のことなので11÷2=5余り1でredetaは5になります。
・条件が真のとき①に戻り、繰り返し処理していきます。
 ☆例:
    スクリーンショット 2022-01-09 150119.png
redeta0になった時点でループから抜けますが、今回はこれで終わりではありません。よく見てみると、出力したい値は1011ですが、ここのansの値は1101です。なので次のループで並び替えをする必要があります。
ansの後ろの値から順にanswerに格納して例のように並べ替えして、
 ☆例:ans   1101 ↓
    answer  1011
 となります。 
・これで10進数の112進数の1011になりました。

#結論

・これで全進数を相互変換できるプログラムができました。
・デザインは、、、
スクリーンショット 2022-01-10 195430.png
こんな感じにしてみました。

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

まとめと今後

・今回はC#で全進数を相互に変換するプログラムを作ってみました。今は誰もが作れるようなプログラムを作ったりし、応用的なものは作れていませんが、今後はこれを応用したプログラムを作ろうと考えています。
・例えば変換過程をtextで表示し、初心者にわかりやすいように改良したり、小数点も変換できるようにしようと考えています。


・ここまで見ていただきありがとうございました。初めてQiitaを書き、文章を分かりやすく書くのは難しいなと思いました。4年間で上手く書けるようになれればなと思います。笑

2
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3