とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

基数変換

値を16進数表示するとき,みなさんはどうしますか? printfの%x, %X変換指定子を使えば良いでしょう。同様に8進数表示するのであれば%o変換指定子を使えばよいです。言うまでもなく10進数表示は%d, %i, %u変換指定子を使えば良いですね。
では値を2進数表示するならどうしますか?
ここでは値をadic進数表示できる関数を紹介します。adicの範囲は2〜62,つまり2進数から62進数まで表現できます。

#include <stdlib.h>
#include <stdio.h>
void PrintAdic(int n, int adic)
{
static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
div_t d;
if (n < 0 || adic < 2 || adic > sizeof(s)-1) exit(1);
d = div(n, adic);
if (d.quot) PrintAdic(d.quot, adic);
putchar(s[d.rem]);
}

int main(void)
{
PrintAdic(15, 2); puts("\t<= 15(10)を2進数表示");
PrintAdic(15, 8); puts("\t<= 15(10)を8進数表示");
PrintAdic(15, 10); puts("\t<= 15(10)を10進数表示");
PrintAdic(15, 16); puts("\t<= 15(10)を16進数表示");
PrintAdic(0x4687, 18); puts("\t<= 4687(16)を18進数表示");
PrintAdic(0121516, 27); puts("\t<= 121516(8)を27進数表示");
PrintAdic(1295, 36); puts("\t<= 1315(10)を36進数表示");
PrintAdic(3843, 62); puts("\t<= 3844(10)を62進数表示");
return 0;
}


実行結果
1111    <= 15(10)を2進数表示
17 <= 15(10)を8進数表示
15 <= 15(10)を10進数表示
f <= 15(10)を16進数表示
31d1 <= 4687(16)を18進数表示
239a <= 121516(8)を27進数表示
zz <= 1315(10)を36進数表示
ZZ <= 3844(10)を62進数表示

ちなみに「10進数を16進数に変換」とか「2進数を8進数に変換」などの表現はおかしいので,使わないようにしましょう。ソース上で10と書こうが0xaと書こうが012と書こうが,コンピュータ内部では同じ値(10)になります。同じ値なので「変換」という表現は間違いであることが分かるでしょう。あくまで人間に見える基数変換後の表示です。
ところで上記PrintAdicでなぜ基数変換できるのでしょうか? 説明は次回。