以前、本ブログで、「基数変換」を取り上げた。↓
割り算を使って、10進数を2進数、8進数、16進数に変換する方法をご紹介している。
今回は、実際にCのプログラムで基数変換してみよう。
読み込んだ10進数を2進数から36進数に基数変換
//読み込んだ10進数を2進数から36進数に基数変換
#include <stdio.h>
/* type型のxとyの値を交換 */
#define swap(type,x,y) do { type t = x; x = y; y = t;} while (0)
/* 整数値xをn進数に変換した数字文字の並びを配列dに格納 */
int card_conv(unsigned x, int n, char d[])
{
char dchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int digits = 0;
if (x == 0) // 0であれば
d[digits++] = dchar[0]; //変換後も0
else
while(x) {
d[digits++] = dchar[x % n]; //nで割った剰余を格納 注(1)
x /= n; // 注(2)
}
for (int i = 0; i < digits /2; i++) //配列dの並びを反転 注(3)
swap(char,d[i],d[digits -i -1]);
return digits;
}
int main(void)
{
puts("10進数を基数変換します");
int retry;
do
{
unsigned no; //変換する整数
int cd; //基数
char cno[512];
printf("変換する非負の整数:");
scanf("%u",&no);
do {
printf("何進数に変換しますか(2-36) :");
scanf("%d",&cd);
} while (cd < 2 || cd > 36);
int dno = card_conv(no,cd,cno);
printf("%d進数では",cd);
for (int i = 0; i < dno; i++)
printf("%c",cno[i]);
printf("です\n");
printf("もう一度しますか(1-yes,0-no) :");
scanf("%d",&retry);
} while (retry == 1);
return 0;
}
実行結果
$ ./a.out
10進数を基数変換します
変換する非負の整数:57
何進数に変換しますか(2-36) :2
2進数では111001です
もう一度しますか(1-yes,0-no) :1
変換する非負の整数:57
何進数に変換しますか(2-36) :8
8進数では71です
もう一度しますか(1-yes,0-no) :1
変換する非負の整数:57
何進数に変換しますか(2-36) :16
16進数では39です
もう一度しますか(1-yes,0-no) :0
$
プログラム内 注(1) xをnで割った剰余を添字とする配列dchar内の文字dchar[ x % n ]を配列dの要素d[digits]に代入し、それからdigitsの値をインクリメントする。(後置増分演算子)
注(2) xをnで割る。
剰余で求めた順に格納していくため、配列dの先頭側が下位桁となる。すなわち、変換後の桁の並びは、求めたい数の並びと逆になる。
そこで、注(3) 配列d内のd[0]~d[digits – 1]の部分の反転を行う。
main関数では、基数変換を対話型で行う。
(参考文献)新・明解C言語で学ぶアルゴリズムとデータ構造第2版 柴田望洋著(SBクリエイティブ)
コメント