16進文字列と数値の変換

 16進の文字列を数値に、あるいは逆に数値を16進の文字列で表してみましょう。こういった処理はたいていのライブラリに入っています(HexToInt など)が、Java にはないようです(と思ったらありました。ご指摘いただいた方々、ありがとうございました)。そこで、どのように処理すれば良いのか考えてみました。

16進文字列を数値に

 16進文字列とは、数値を16進数で表現した文字列です。16進の文字列を数値に変換する時、一桁なら簡単ですね。0〜9ならそのまま数値になりますし、aなら10、bなら11.....そしてfなら15、という感じです。これをプログラムにするなら、以下のような感じになるでしょう。このプログラムでは、sが16進の文字でrが結果の数値になります。

  switch (s) { /* 16進一文字を数値に変換 */

    case '0':
        r=0;
        break;

    case '1':
        r=1;
        break;

    case '2':
        r=2;
        break;
      ・
    (中略)
      ・
    case 'e':
        r=14;
        break;

    case 'f':
        r=15;
        break;

  }

 では、次に二桁を考えてみましょう。16進二桁は00〜ff、数値としては0〜255になります。16進数では、一桁上の数字が16倍の「重み」を持っているので、一桁めは単純に一桁の処理をして、2桁めは一桁目のように数値にした後16倍すれば良いはずです。
 例えば、0aとa0を考えてみます。0aの場合は、一桁目のaを数値にして10です。a0の方は、aを数値にすると10ですが、aは2桁目にあるので16倍して160。つまりa0は160になります。3桁、4桁も同様に考えると、結局以下のようなアルゴリズムで16進の文字列を数値に変換できる事になります。

 1.文字列の最下位一文字を操作対象とする。

 2.操作対象の文字を数値に変換(0〜15)

 3.2の数値に桁数に応じた「重み」を掛け、その数値を記憶。

 4.一桁上の一文字を操作対象として2に戻る。

 5.最上位まで処理できたら、3の結果を合計する。

・例

 16進文字列「abcd」を数値にする。

  最下位d を数値にすると13
 2桁目c は12×16=192
 3桁目b は11×16=2816
 4桁目a は10×16=40960

 よって結果は13+192+2816+40960=43981。

 以上の事をまとめて、16進の文字列を渡すとその文字列が表す数値を返す関数を作れば、以下のようになるでしょう。

  private int HexToInt(String str) { /* 16進文字列を数値に */

      char s[];
      int a,i,r;

      a=1; /* 加算対象となる桁の「重み」 */
      r=0; /* 結果 */

      s=str.toCharArray(); /* 文字列を配列に */

      for (i=str.length()-1;i>-1;i--) { /* 一字づつ取り出す */

          switch (s[i]) { /* 一字取り出し文字の数値を加算 */

              case '0':
                  r+=a*0;
                  break;

              case '1':
                  r+=a*1;
                  break;
                   ・
        (中略)
                   ・
              case 'e':
                  r+=a*14;
                  break;

              case 'f':
                  r+=a*15;
                  break;

          }

          a*=16; /* 一つ上の桁の「重み」を求める */

      }

      return r; /* 結果の数値を返す */

  }

数値を16進文字列に

 数値を16進の文字列にする、という事は16進数に「書き下す」という事です。これは、単純に数値を16進一桁(4ビット)づつ処理していけば良いでしょう。まず、最下位の1桁を得るために数値と16進0fの論理積を求めます(あるいは、数値を16で割った「余り」を求めても良い)。この結果は0〜15で、これを16進にしたものが文字列の一桁目になるわけですね。次に、2桁目を求めるために数値を1桁「ずらす」事にしましょう。すでに一桁目を求めたので、その桁を「捨てて」やれば最下位に2桁目がきます。1桁目を捨てるには、4ビット(16進一桁分)右シフト(あるいは16で除算)すれば良いでしょう。後は、1桁目と同様に0fとの論理積をとり16進一桁の文字にすれば、それが2桁目です。
 以下、3桁目、4桁目、と同様にしていけば16進文字列を得る事が出来ます。今回は、数値として32ビット型整数を用いるので、この処理を8回行えば良いでしょう。関数にすると、以下のような感じです。

  private String IntToHex(int n) { /* 数値を16進文字列に */

      int i;
      String res,rest;

      res="";

      for (i=0;i<8;i++) { /* 32ビット整数を16進一桁づつ変換 */

          switch (n & 0xf) { /* 最下位一桁の数値を検査 */

              case 10:
                  res+="a";
                  break;

              case 11:
                  res+="b";
                  break;

              case 12:
                  res+="c";
                  break;

              case 13:
                  res+="d";
                  break;

              case 14:
                  res+="e";
                  break;

              case 15:
                  res+="f";
                  break;

              default: /* 0〜9はそのまま数字に */
                  res+=String.valueOf(n & 0xf);

          }

          n=n>>4; /* 4ビット左シフトして一桁ずらす */

      }

      rest="";

      for (i=7;i>-1;i--) /* 文字列を左右反転 */
          rest+=res.substring(i,i+1);

      return rest;

  }

 上の関数では、最下位の桁から順に文字列に足していっているため、そのままでは最下位が一番左端(文字列の先頭)に、最上位が右端(文字列の末端)に来てしまいます。そのため、処理が終わった後で文字列を左右反転する事にしました。

プログラム

 今回のプログラムには、10進表記の文字列(Int)と16進表記の文字列(Hex)を入れるテキストフィールドがあります。どちらかに適当な文字列を入れたら、「IntToHex」で10進文字列を16進文字列に、「HexToInt」で16進文字列を数値に変換してみてください。例えば、Int のテキストフィールドに「255」と入力してから「IntToHex」ボタンをクリックすると、Hexの方のテキストフィールドに255が8桁の16進の文字列として「000000ff」と表示されます。
 なお、16進のアルファベットはすべて小文字にしてください。

プログラムソース表示
戻る