#背景
競技プログラミング、ちょくちょく進数変換をする機会がありますよね。
2進→10進変換とか16進→2進変換とか、よくある数値ならいいのですが、
たまに中途半端な数字の進数変換を求められることがあります。
そんなときのために、任意の進数から任意の進数へ変換する関数を作りました。
テストは最低限の確認しかしていないので、抜け漏れあるかも。
#使い方
-
#include<string>
が必要です。 - 入力文字列は最大36進数の文字(0〜9,A,B,...,Z)まで対応しています。
- 入力文字列を37進数以上と見なすことも可能です。
- 出力は36進数までの対応です。
- 不正入力に対するエラーは、実装していません。(時間があればやる)
n_ary("10110011", 2, 10); //出力値:179
n_ary("511", 10, 16); //出力値:1FF
n_ary("5Z", 36, 10); //出力値:215
n_ary("5XZ", 1000000, 10); //出力値:5,000,033,000,035
#ソースコード
###メイン処理:string n_ary(string, int, int)
!自作関数を3つ使用しています。コピペで使用する際は後述のサブルーチンも合わせて使ってください!
/* 関数名 n_ary(string str, int n, int m)
説明 n 進数で表現された数値を文字列 str で受け取り、m 進数に直して文字列で出力する。
使用ライブラリ string
使用自作関数 ntodec, decton, pow_ll
制約事項 36進数までの対応。負の値には対応していない。
*/
string n_ary(string str, int n, int m){
unsigned long tmp = 0;
string ret;
for(int i=0; i<str.length(); i++){
tmp += (unsigned long) ntodec(str[str.length()-1-i]) * pow_ll(n, i);
}
if(tmp==0) return "0";
while(tmp!=0){
ret = decton(tmp%m) + ret;
tmp/=m;
}
return ret;
}
###サブルーチン1:N進→10進変換 (N≦36)
文字 0〜9, A〜Z を 0〜35 の整数に変換する関数です。
クリックでソースコードを表示
/* 関数名 ntodec(const char c)
説明 char で 文字{0,1,2,...,9,A,B,...,Z} を受け取り、
int で {0,1,2,...9,10,11,...,35}に直して返す。
それ以外の文字が来た場合は-1を返す。
使用ライブラリ なし
*/
int ntodec(const char c){
switch(c){
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'A': return 10;
case 'B': return 11;
case 'C': return 12;
case 'D': return 13;
case 'E': return 14;
case 'F': return 15;
case 'G': return 16;
case 'H': return 17;
case 'I': return 18;
case 'J': return 19;
case 'K': return 20;
case 'L': return 21;
case 'M': return 22;
case 'N': return 23;
case 'O': return 24;
case 'P': return 25;
case 'Q': return 26;
case 'R': return 27;
case 'S': return 28;
case 'T': return 29;
case 'U': return 30;
case 'V': return 31;
case 'W': return 32;
case 'X': return 33;
case 'Y': return 34;
case 'Z': return 35;
default : return -1;
}
}
###サブルーチン2:10進→N進変換 (N≦36)
0〜35 の整数を文字 0〜9, A〜Z に変換する関数です。
クリックでソースコードを表示
/* 関数名 decton(const int n)
説明 int で 数値 0〜35 を受け取り、文字{0,1,2,...,9,A,B,...,Z}に直して char で返す。
それ以外の数字が来た場合は \0 を返す。
使用ライブラリ なし
*/
char decton(const int n){
switch(n){
case 0: return '0';
case 1: return '1';
case 2: return '2';
case 3: return '3';
case 4: return '4';
case 5: return '5';
case 6: return '6';
case 7: return '7';
case 8: return '8';
case 9: return '9';
case 10: return 'A';
case 11: return 'B';
case 12: return 'C';
case 13: return 'D';
case 14: return 'E';
case 15: return 'F';
case 16: return 'G';
case 17: return 'H';
case 18: return 'I';
case 19: return 'J';
case 20: return 'K';
case 21: return 'L';
case 22: return 'M';
case 23: return 'N';
case 24: return 'O';
case 25: return 'P';
case 26: return 'Q';
case 27: return 'R';
case 28: return 'S';
case 29: return 'T';
case 30: return 'U';
case 31: return 'V';
case 32: return 'W';
case 33: return 'X';
case 34: return 'W';
case 35: return 'Z';
default : return '\0';
}
}
###サブルーチン3:べき乗計算(long long型)
long long
で$x^n$を計算します。
std::pow
で桁数が足りないとき用に作ったものです。
double
型で事足りる場合はstd::pow
で十分ですので、本関数は必須ではありません。
クリックでソースコードを表示
/* 関数名 pow_ll(long long x, long long n)
説明 x^n を計算する。long long 対応
使用ライブラリ なし
*/
inline long long pow_ll(long long x, long long n){
long long ret = x;
if(n==0) return 1;
for(long long i=1; i<n; i++){
ret *= x;
}
return ret;
}
#まとめ
この関数さえ仕込んでおけば、N進数からM進数への変換が簡単に行えると思います。
注意すべき点としては、以下でしょうか。
- 小数に対応していない
- 負の数に対応していない
- 不正入力に対応していない
- 雑なテストしかしていない(ごめんなさい)
ただし不正入力に関しては、decton()
とntodec()
において 0〜9、A〜Z
以外の入力があった場合に -1
や \0
をリターンする仕様になっているのでうまく利用してください。