R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

p進数を計算する処理

ふと必要になったので作ってみました。


#region AdicNumber Method
///*********************************************
/// <summary>
///    p 進数に変換した値を取得します</summary>
/// <param name="codeList">
///    1桁で表現できる一意な文字の列を2文字以上で指定します。
///    最も左の文字が 0 に、1文字右に移動するごとに +1 の値を表す文字になります。
///    例えば16進法なら、"0123456789ACDEF" のように指定して下さい。</param>
/// <param name="value">
///    変換する元となるゼロ以上の数値を指定します。</param>
/// <returns>
///    変換した結果です。
///    10進法以下であっても常に文字列型を戻します</returns>
/// <remarks>
///    codeList に1文字以下の文字列を指定した場合は、常に空の文字列を返します。</remarks>
///*********************************************
static public string AdicNumber(string codeList, long value) {
  // 引数チェック
  if (value < 0) {
    throw new ArgumentException("ゼロ以上の数値のみ指定できます。", "value");
  }
  
  int p = codeList.Length; // codeList の長さ = (p 進法)になる。
  if (p < 2) {        
    throw new ArgumentException("2文字以上指定して下さい。", "codeList");
  }

  for (int i = 0; i < codeList.Length - 1; ++i) {
    for (int j = i + 1; j < codeList.Length; ++j) {
      if (codeList[i].Equals(codeList[j])) {
        throw new ArgumentException("同じ文字が含まれています。", "codeList");
      }
    }
  }

  // 戻り値を格納するための List オブジェクトを生成。
  System.Collections.Generic.List<string> ret;
  ret = new System.Collections.Generic.List<string>();
  do {
    int remain = (int)(value % p); // (基数 / p) の剰余を求める。
    ret.Add(codeList[remain].ToString()); // その桁の文字を追加。
    value = (value - remain) / p; // 絶対に割り切れる。この値を次の基数。
  } while (value > 0);
  ret.Reverse(); // 先頭の要素の位が一番低くなっているため逆順にする。
  return String.Join("", ret.ToArray());  // 連結した文字列を返す。
}

#endregion


0~1024 を

16進数

で取得する場合は、以下のように使います。


 static void Main() {
  for (int i = 0; i <= 1024; ++i) {
    System.Diagnostics.Debug.WriteLine(
      i.ToString() + ":" + AdicNumber("0123456789ABCDEF", i)
    );
  }
}


元は、自動パスワード生成とか、コード番号生成に利用しようと思ったんですが、

AdicNumber("0123456", 値) これで7進数。

AdicNumber("わんくま同盟",値) こうすると6進数を「わんくま同盟」で表現w

などと、いろいろできるなぁ。

投稿日時 : 2007年2月4日 16:12

Feedback

# re: p進数を計算する処理 2007/02/04 16:36 R・田中一郎

あれ?
文字列の重複チェック機能をつけた方がいいのかな?

# re: p進数を計算する処理 2007/02/04 19:42 Hirotow

http://hcm.wankuma.com/aspx/other/adicnumber.aspx
面白そうだったのでWEBフォームで組んでみました。
123(クマー) = マママークw

# re: p進数を計算する処理 2007/02/04 19:58 R・田中一郎

Hirotow さん

試してみました。
面白すぎ!www

しかも、ちょっとハマる。

# re: p進数を計算する処理 2007/02/04 22:00 επιστημη

> 文字列の重複チェック機能をつけた方がいいのかな?

ついでにcodeList.Length > 1 をチェックすべ。

# re: p進数を計算する処理 2007/02/04 22:03 επιστημη

/* 逆関数 */

static public long revAdicNumber(string codeList, string value) {
 long result = 0;
 for ( int i = 0; i < value.Length; ++i ) {
  result *= codeList.Length;
  result += codeList.IndexOf(value[i]);
 }
 return result;
}

# re: p進数を計算する処理 2007/02/04 22:27 匿名

使用する文字を一文字にすると Runtime Error

# re: p進数を計算する処理 2007/02/04 22:40 ネットクラゲ

codeListにサロゲートペアを含めると・・・

# re: p進数を計算する処理 2007/02/04 22:46 Hirotow

>使用する文字を一文字にすると Runtime Error
ほんとだ。
明日逆関数とこのバグの修正を追加してみます。
というかおもろいな。これ。

# re: p進数を計算する処理 2007/02/05 0:19 THREE-ONE

List<char> ret = new List()<char>;
do {
int remain = (int) (value % p);
ret.Add(codeList[remain]);
value = (value - remain) / p;
} while (value > 0);
ret.Reverse();
return new string(ret.ToArray());
}
たいした違いじゃないけどこうかなー、インデクサを使えば char の配列にする意味ないと思う。
あと、少し気になるのがコメント。
ドキュメントコメントで自然数といいながら 0 なら正常終了として空文字返してるし。(自然数とは 1 以上の整数です。)
「正の整数のみ指定できる」という例外メッセージのための判断条件が 0 未満なのもおかしい。(普通 0 は正負どちらにも属しません)

ごめんなさい、数学科出身なもので気になってしまうのです。
無粋なコメントでごめんなさい。

# re: p進数を計算する処理 2007/02/05 10:17 Hirotow

ちなみにretって何型?

# re: p進数を計算する処理 2007/02/05 11:41 Hirotow

http://hcm.wankuma.com/aspx/adicnumber/Default.aspx
いろいろ機能追加して再登場。
 ・プリセットの最適化?
 ・逆変換・相互変換機能対応
 ・例外処理
 ・コピーライト追加
 ・少しかっこよくなったかも

# re: p進数を計算する処理 2007/02/05 19:20 シャノン

おー。数字を任意の文字で表すって面白いな。
簡易暗号に使えそうw
変換先、変換元ともにひらがなとか使って、一見して意味がある文なんだけど、これに通すと全然違う意味になるとかw

# re: p進数を計算する処理 2007/02/06 15:22 R・田中一郎

επιστημη さん

>ついでにcodeList.Length > 1 をチェックすべ。

これは気付かなかったです!
やべーっすね^^;
修正しておきました。

>/* 逆関数 */

ありがとうございます。
後で作ろうと思っていたので、助かりました _(_*_)_

---------------------------------------------------
匿名 さん

>使用する文字を一文字にすると Runtime Error

επιστημη さんの言うチェックが抜けているからですね。

---------------------------------------------------
ネットクラゲ さん

>codeListにサロゲートペアを含めると・・・

この辺は深く考えないことにしています^^;

---------------------------------------------------
Hirotow さん

>というかおもろいな。これ。

英数字だとつまらないんですけど、ひらがなを使うと楽しくなりますね。

>ちなみにretって何型?

ソースは、string 型ですよ。
String.Join() が使いたかったので^^;

>・少しかっこよくなったかも

凄くかっこよくなりました。

---------------------------------------------------
THREE-ONE さん

>codeList[remain]

確かに。この方がすっきりしますね。

>あと、少し気になるのがコメント。

この点については、仕様があやふやになっていたため、妙なコメントになっちゃっていましたね。
わかりやすい表現に修正しました。

---------------------------------------------------
シャノン さん

>簡易暗号に使えそうw

今度使ってみようかな・・・

# p進数変換フォーム Version2.1 2007/02/06 19:29 Hirotow's Craftive Blogs

p進数変換フォーム Version2.1

# p進数変換フォーム Version2.1 2007/02/06 19:49 Hirotow's Craftive Blogs

p進数変換フォーム Version2.1

タイトル
名前
Url
コメント