C/C++で、10進数を2進数に変換して表示する

ブログ

左手の筋肉痛に苦しみながら書いています、わたすけです。

タイトル通り、「10進数を2進数に変換して表示する」プログラムをかなり頑張って書いたので、今回はやり方を説明します。

スポンサーリンク

いきなりどうした

なんでこんなことしたのかというと、深いようで浅い訳があります。

本日、授業で実習があって、C言語でプログラムを書くことになりました。その時の課題は「入力された10進数の値を2進数に変換して表示する」。

C言語は(少なくとも授業では)まだ基本しかやっておらず、応用的な問題を作るには知識も時間もたりないと判断され(実際この通りに判断されたのかどうかは知らないですが)、「入力は16未満である」という制約が課されました。

授業で示された解決方法は「変数を3つ用意し、”入力を2で割った値をそのうち1つの変数に入れる”という動作を3回繰り返す」というやり方でした。

しかし。

これではあまりにも範囲が狭すぎます。それに、「変数を3つ用意」なんていうやり方は非常に好ましくないです。

ということで、授業が終わってから、家でC言語で実装することにしました。また、ついでにC++でも書きました。今回は成果物の紹介と、プログラムの説明をします。

制約

できるだけ授業で習ってないことやりたくないな~と思ったので、配列は使わないようにしました。そのわりにはまだ習ってない関数使ってますが、まあ簡単な関数なのでいいかなぁと思ってます。

成果

こちら(GitHub Gist)です。

同級生に見せるためにかなりコメント書いているので正直これのコピペみたいな記事になってしまいますが、ゆるしてください・・・

C言語版

(入力された値をinput、答えをansとして解説します)

C言語版では、文字列を使わずに計算しました。

計算の基本的な考えは「inputを2でわったあまりをansの左に追加していく」という感じです。
分かりづらい表現ですが、例えば10という数字があって、この左に1を追加するには、100を足せばいいですよね?(10+100=110)
このようにして計算していきます。これをinputが0になるまで繰り返せば、出てきます。

このようにすると、例えば5 (0b101) の計算手順は以下のとおりです。

  1. 入力をinputに格納、ansを0で初期化
  2. 5÷2=2あまり1、ansに1を追加11
  3. 2÷2=1あまり0、ansに1を追加して01
  4. 1÷2=0あまり1、ansに1を追加して101
  5. inputが0なので終了、答えは101

しかし、これだとある問題があります。今回は文字列を使っていないため、ansは数字であるはずです。しかし、「01」という数字は存在しません。これはこまった。

ということで、全ての位に1を足しておき、あとで足した分を引いてやればいいということです。今回の場合、212という数字にしておき、あとから111を引いてやれば101という数字が出てきます。

と、ここまで書いてて思ったけど、別に1足さなくても良かったのでは・・・?泣きそうです。

そんな感じで計算していくと、例えば入力が65535だった場合、出力は10000000000000000になります。2進数と見ると大したことないのですが、これをint型の変数に入れようと思っても大きすぎて入りません。このため、クソデカ変数型のunsigned long longを使っています。

C++版

C++版はもっと単純です。inputを2で割ったあまりを文字列の右にどんどん追加していき、出力時に文字列を反転させるだけです。とてもかんたんですね。

inputを2で割ったあまりはもちろん数字なので、これを文字列型の変数に追加していくためにはstd::ostringstreamを使う必要があるらしいです。sstreamをインクルードしましょう。

この2つの違いは?

C言語版とC++版の違い、最大の特徴は「処理可能な数字の範囲」にあります。

C言語で書かれた方は最大1,048,575まで処理できますが、
C++で書かれた方はなんと18,446,744,073,709,551,615まで変換できます!!!

流石にC言語側の実装があまり良くないのもあると思いますが、C++版は5分でさっくり書いたので、なんだかちょっと悲しみを感じます。

もう少し改善点があったら聞いてみたいです。

実行結果

C言語版とC++版で、「536850」と、それぞれの処理可能な最大数を2進数で表示させています。

実行環境はWindows + MinGWです・・・

C言語版

「536850」という数字はGoogleで乱数を使って出したので意味はないです

C++版

マジで桁違いで草

ちなみに

これ以外にも、C言語のビット演算子(詳しくないので間違っている可能性あり)である&を使うことでより簡潔に記述できるらしいですが、流石にやる気が起きませんでした。

終わりに

ここ最近、自分のポインタやメモリ関連に関する知識不足を実感する機会が増えており、とてもいいなと思います。最近はCではなくRustやTypeScriptを勉強していますが、今後の授業でも確実に必要になってくると思うので、頑張っていきたいと思います。

ということで、10進数を2進数に変換して表示するプログラムと、その解説でした。今月はもう一回記事を書くので、よろしくおねがいします。

コメント

タイトルとURLをコピーしました