2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C++】数値のみの文字列をN進数表記の値と見なし、10進数に変換する

Last updated at Posted at 2021-02-21

背景

競プロのコンテスト用に必要になったので、作りました。
また N 進 → 10 進変換としても使えると思います。
なお負の入力値は想定していません。ご了承ください。

できること

数値(0〜9)のみで表現された N 進数の値を 10 進数に変換する。(N ≦ 10)

使用例

2進数の数値"10110011"を10進数に変換する
cout << conv_ary("10110011", 2); //出力値:179

$\scriptsize 1\times2^7+0\times2^6+1\times2^5+1\times2^4+0\times2^3+0\times2^2+1\times2^1+1\times2^0 = 179$

7進数の数値"01234567"を10進数に変換する
cout << conv_ary("0123456", 7); //出力値:22875

$\scriptsize 0\times7^6+1\times7^5+2\times7^4+3\times7^3+4\times7^2+5\times7^1+6\times7^0 = 22875$

1024進数の数値"256"を10進数に変換する
cout << conv_ary("256", 1024); //出力値:2102278

$\scriptsize 2\times1024^2+5\times1024^1+6\times1024^0 = 2102278$

エラーの例...8進数の数値"12345678"を10進数に変換する
cout << conv_ary("12345678", 8); //出力値:-1

8 進数では 0〜7 のみが使用できるため、8 は不正入力となり -1 が return されます。

エラーの例...16進数の数値"0ff0"を10進数に変換する
cout << conv_ary("0ff0", 16); //出力値:-1

入力文字列に数値以外の文字(f)が含まれるため、不正入力となり -1 がリターンされます。

ソースコード

/*  関数名          conv_ary(string IN, unsigned long long ary)
    説明            stringで数字の文字列を受け取り、ary進数と見なしたときの値を10進数(long long)で返す
    使用ライブラリ  string
    使用関数        pow_ll, ctoi
*/
long long conv_ary(string IN, long long ary){
//  cout << __func__ << ", " << __LINE__ << ": IN= " << IN << ", ary=" << ary << endl; // debug用

    /* エラーチェック */
    short max=0;
    for(int i=0; i<IN.length(); i++){
//      cout << __func__ << ", " << __LINE__ << ": IN[" << i << "]= " << IN[i] << endl; // debug用

        /*  入力文字列に0〜9以外の文字が含まれていた場合はエラーとして -1 を return する */
        if(isdigit(IN[i])==false) return -1;
        
        /*  入力文字列に指定の進数では使えない文字が含まれていた場合、エラーとして -1 を return する
            例えば IN = "124", ary = 3 のとき、4 は 3 進数で扱えないためエラーとなる */
        max = ctoi(IN[i]);
        if(max>=ary) return -1; 
    }
    /* エラーチェックここまで */

    long long ret=0;
    for(int i=0; i<IN.length(); i++){
        ret += (long long) ctoi(IN[IN.length()-1-i]) * pow_ll(ary , i);
    }
//  cout << __func__ << ", " << __LINE__ << ": return=" << ret << endl; //debug用

    return ret;
}

解説

関数のメイン処理

  • long long conv_ary(string IN, long long array)
  • 文字列 (IN) と「何進数と見なすか」の情報 (ary) を受け取ります。
  • IN の中に含まれる文字は 0〜9 の数値である必要があります。
  • ary は long long 型の範囲内で対応しています。つまり 9,223,372,036,854,775,807 進数も可能。
  • return はとりあえず long long 型としていますが、必要に応じて変更してください。


  • エラーチェック
  • 必要ない場合は削除するかコメントアウト、またはディレクティブ#ifdefなどで外してください。
  • 何をしているかはコメントに書いてあります。
  • ary としてありえない数字(1 進数、0 進数、または負の値)を受け取った場合もここでエラーとなります。


  • for(int i=0; i<IN.length(); i++){ ... }
  • IN に含まれる全文字について、1つずつ参照していくためのループです。

    各桁について 10 進変換し、1 桁ずつ結果を足し合わせていく方法を取りました。


  • ret += (long long) ctoi(IN[IN.length()-1-i]) * pow_ll(ary , i);
  • ctoi(IN[IN.length()-1-i])

    入力文字列 IN の右から i 番目の文字を取り出し、関数 ctoi(char)を用いて数値に変換しています。
  • pow_ll(ary , i)

    ary の i 乗を計算しています。

    cmath ライブラリの pow 関数は double 型なので、より大きい値を計算できるように long long 型のべき乗計算関数を用意し使用しています。
  • ret += ...

    各桁の 10 進変換した値を足し合わせていく処理です。

サブルーチンその1: ctoi(const char)

こちらの記事のコードを使用しています。
char が表す数字を int へ変換したい @EqualL2
https://qiita.com/EqualL2/items/b4683db7ab4e90545bb2

サブルーチンその2: pow_ll(long long, long long)

/*  関数名          pow_ll(long long x, long long n)
    説明            x^n を計算する。long long 対応
    使用ライブラリ  なし
*/
long long pow_ll(long long x, long long n){
    long long ret = x;
//  cout << __func__ << ", " << __LINE__ << ": x= " << x << ", n=" << n << endl; // debug用
    if(n==0) return 1;
    for(long long i=1; i<n; i++){
        ret *= x;
    }
//  cout << __func__ << ", " << __LINE__ << ": return=" << ret << endl; // debug用

    return ret;
}

とりあえず long long にしていますが、必要に応じてlong なり int に変更してください。
今回のコードに関して言えば、n は int で受け取るべきでした。反省。

あとがき(課題とか)

今回は 10 進数で書かれた数値(文字列) を N 進数に読み替えたらどうなるか? というコンセプトで作りました。
その場で雑に作ったものなので、処理高速化の余地はあると思います。

完全な N 進 → M 進変換とか作っておきたいですね。
→できました。https://qiita.com/Shiro-san/items/9376c8898a0882482a6a

2
1
0

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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?