前回 の続き
前回は10進数を16進数に変換したり,2進数を10進数に変換するマクロを作りました.そうすると,2進数を16進数に変換したくなりますね.
これは$\verb|\DTH|$と$\verb|\BTD|$を組み合わせれば良さそうに思いますが,実はここに大きな落とし穴があって,前回の実装方法ではうまくいきません(というより,前回は組み合わせることを想定した実装にしていませんでした).
うまくいかない理由を説明します.とは言っても,Mathlog で$\mathrm\TeX$言語のあれやこれやを話すのは少し憚られるので簡潔に言うと,$\verb|\BTD|$を(先頭)完全展開させようとしたとしても,再帰によって条件分岐に用いたトークンである$\verb|\else|$と$\verb|\fi|$が残ることで,数値を受け取るはずの$\verb|\DTH|$にそれらが渡されてエラーが起きるのです.
そこで,条件分岐の処理を分離することでこの問題を解決します.
\def\xx@ifx#1{%
$\quad$\ifx\xx@relax#1\xx@relax
$\qquad$\expandafter\@firstoftwo%
$\quad$\else
$\qquad$\expandafter\@secondoftwo%
$\quad$\fi%
}
\def\xx@ifnum#1{%
$\quad$\ifnum#1<16
$\qquad$\expandafter\@firstoftwo%
$\quad$\else
$\qquad$\expandafter\@secondoftwo%
$\quad$\fi%
}
を定義し,$\verb|\xx@DTH|$と$\verb|\xx@BTD|$の定義を次のように書き直します.
\def\xx@DTH#1#2{%
$\quad$\xx@ifnum{#1}
$\qquad${\xx@DTA{#1}#2}
$\qquad${\xx@DTH{\the\numexpr(#1*2-16)/(16*2)\relax}{\xx@DTA{\the\numexpr#1-(#1*2-16)/(16*2)*16\relax}#2}}%
}
\def\xx@BTD#1#2#3\xx@relax{%
$\quad$\xx@ifx{#3}
$\qquad${\the\numexpr#1*2+#2\relax}
$\qquad${\xx@BTD{\the\numexpr#1*2+#2\relax}#3\xx@relax}%
}
この修正により,たとえば
$$
\verb|\expandafter\DTH\expandafter{\romannumeral-`?\BTD{1100100}}|
$$
などとすると,2進数の1100100が16進数の64に変換されて出力されます.
これでもう安心して進数変換ができますね!
それではみなさま,よき$\mathrm\TeX$ライフを.