📎

TeXでの整数を扱う三つの方法

に公開

0.はじめに

TeX(特に e-TeX 拡張を前提とした場合)において「整数」を取り扱う方法のうち,character・number・counter という3種類の概念と,それら相互の変換を6パターン解説します。

  • character: "1", "2", "12" などの 数字を表す文字列
    • 今回は一桁だけ ("1") のケースも二桁以上 ("12") のケースも共に考えます
  • counter: カウンタで管理される 整数
  • number: TeX エンジン内部で扱われる 整数\numexpr ... \relax などで数値計算できる対象。

counterもnumberも内部的には同じ整数ですが、前者は名前で管理されるのに対し、後者は制御綴で管理されます。

  • number : \hogeなどの制御綴に格納される。\newcountがこれにあたる。
  • counter : LaTeXでは\newcounterで定義される。
\newcount と \newcounterの違い
  1. \newcount
  • LaTeXの原型であるPlain TeXの命令。
  • 汎用的な整数カウンターを作成します。
  • シンプルに整数の値を保持するために使われ、段落番号や特定のカスタムカウントに便利です。
  • リセット機能がありません。自分でリセットする必要があります。
\newcount\mycount  % カウンターを新しく作成
\mycount=5         % 値を設定
\advance\mycount by 1 % 値を加算
\the\mycount       % 現在の値を出力
  1. \newcounter
  • LaTeXの命令で、LaTeXドキュメント内のカウンター管理を簡単にするために作られています。
  • 文書のセクション番号や、図表、項目リストなどの自動カウンターを管理するのに向いています。
  • スコープごとのリセット機能があります。例えば、セクションごとに図表の番号をリセットすることが可能です。
\newcounter{mycounter} % カウンターを新しく作成
\setcounter{mycounter}{5} % 値を設定
\stepcounter{mycounter}   % 値を1増加
\arabic{mycounter}        % 現在の値をアラビア数字で出力
  1. 主な違い
機能 \newcount \newcounter
対応環境 Plain TeX, LaTeX LaTeX専用
リセット機能 なし 章や節ごとのリセットが可能
使い方 シンプルな整数管理 文書構造に基づく自動カウンター
追加命令 手動加算、減算 \stepcounter\addtocounterなど

1. TeX における整数の扱い

1.1 character(文字列)

文字列としての "12" は TeX から見ると “1” と “2” の文字トークンの連なりです。
一桁の場合の "3" などは、文字トークンが1つだけになるだけで基本的には同じ考え方です。

1.2 number(内部整数)

TeX では整数演算をする際に、\numexpr ... \relax(e-TeX)や Plain TeX の \number などを介して処理します。

  • \numexpr 12 \relax → “12” という整数値
  • \numexpr 12\relax → とすれば 12 が取得できます。
  • 一桁の場合でも \numexpr 3 \relax とすれば 3 が取得できます。

1.3 counter

counterを使うと、整数を格納しておくことができます。

\newcounter{mycounter} % カウンターを新しく作成
\setcounter{mycounter}{5} % 値を設定
\stepcounter{mycounter}   % 値を1増加
\arabic{mycounter}        % 現在の値をアラビア数字で出力

2. 変換方法

ここからは以下の6種類の相互変換パターンを具体例とともに示します。
数字が一桁 ("3") でも二桁 ("12") でも同様の手順です。

  1. character → number
  2. number → character
  3. number → counter
  4. counter → number
  5. character → counter
  6. counter → character

前提として、「character」は "12""3" のような数字文字列、「number」は e-TeX の \numexpr 等で扱える内部整数とします。

2.1 character → number

目的

"12" のような文字列(あるいは "3" のような一桁文字列)を、TeX が演算できる整数(number)に変換したい

方法

  • e-TeX の \numexpr は、文字列として渡された「数字」をそのまま整数として読んでくれます。
  • 例えば以下のように書くと、#1"12" でも "3" でも問題なく整数として読み取ります。
% #1 は "12" や "3" のような数字文字列を想定
\def\CharacterToNumber#1{%
  \numexpr #1\relax
}

\CharacterToNumber{12}  % -> 12
\CharacterToNumber{3}   % -> 3
\relaxとは?

TeXの\relaxは、特定の動作を持たないプリミティブコマンドで、主にマクロの展開抑制や条件分岐の制御に使用されます。以下に具体的な例を挙げて説明します。

  1. マクロの展開抑制
    \edef内で特定のコマンドの展開を防ぐ際に\relaxを使用します。
\def\name{John}
\edef\greeting{Hello, \name\relax!}

この場合、\relaxがないと、\nameが展開されてしまいますが、\relaxを挿入することで、\nameの展開を抑制できます。

  1. 条件分岐の制御
    \if系の条件分岐で、予期しないトークンの読み込みを防ぐために\relaxを挿入します。
\ifmmode\relax
  % 数式モードの場合の処理
\else
  % 通常モードの場合の処理
\fi

このように、\ifmmodeの直後に\relaxを置くことで、条件判定が意図した通りに行われるようになります。

  1. 単位の後に挿入して曖昧さを回避
    \hskip\vskipで長さを指定する際、\relaxを用いて曖昧さを避けます。
\hskip 2.5pt\relax

\relaxを挿入することで、\hskipが後続のplusminusを誤って解釈するのを防ぎます。 

  1. 式の終了の明示
    以下の例では、\numexpr によって 5 + 3 の計算が行われ、結果は 8 になります。
    \relax がないと、次に続く別のトークンが整数式の一部として解釈されてしまう恐れがあります。
\newcount\result
\result=\numexpr 5 + 3 \relax
\the\result
  • 上記マクロは123という整数値を返します。

\numexprは本来は計算用マクロなので以下のように使えます。

% 加算
\numexpr 12 + 3 \relax \par % -> 15

% 減算
\numexpr 12 - 3 \relax \par % -> 9

% 乗算
\numexpr 12 * 3 \relax \par % -> 36

% 除算(商のみ)
\numexpr 12 / 3 \relax \par % -> 4

2.2 number → character

目的

12 (number) を "12" (文字列) として出力あるいは取得したい

方法

\the\hoge と書くと、\hoge (number) を文字列に展開してくれます。

% #1 は "12" や "3" のような数字文字列を想定
\def\CharacterToNumber#1{%
  \numexpr #1\relax
}

\the\CharacterToNumber{12}  % -> “12”
\the\CharacterToNumber{3}   % -> “3”
  • 上記マクロは"12""3"という文字列を返します。\the で数値を文字列化しています。

2.3 number → counter

目的

number を任意のカウンタに代入したい

方法

numberはそのままcounterに代入できます。

\newcounter{mycounter}

\newcommand{\NumberToCounter}[1]{%
  \setcounter{mycounter}{\numexpr#1\relax}
}

\NumberToCounter{3}
\arabic{mycounter} % -> 3

\NumberToCounter{12}
\arabic{mycounter} % -> 12

2.4 counter → number

目的

カウンタの値を number として扱いたい(たとえば演算したい)

方法

\value{mycounter} とすればいいです。

\newcounter{mycounter}

\setcounter{mycounter}{3}
\value{mycounter} % -> 3

\setcounter{mycounter}{12}
\value{mycounter} % -> 12

2.5 character → counter

目的

"12" のような数字文字列(あるいは "3" のような一桁文字列)をカウンタに直接代入したい

方法

  • \newcounterと\setcounter` で定義します(初期値は0)
  • \stepcounterで簡単に1増加できます
\newcounter{hoge}

\setcounter{hoge}{3}
\Roman{hoge} % => "III"
\setcounter{hoge}{12}
\Roman{hoge} % => "XII"
\stepcounter{hoge}
\Roman{hoge} % => "XIII"

2.6 counter → character

目的

カウンタを文字列として取得したい

方法

\arabic{mycounter}でアラビア数字で出力できます。

\newcounter{mycounter}

\begin{document}

\setcounter{mycounter}{3}
\arabic{mycounter}

\setcounter{mycounter}{12}
\arabic{mycounter}

3. まとめ

TeX で整数を扱うにあたって、次の3要素をしっかり区別するとマクロの設計が理解しやすくなります。

  1. character: "12", "3" などの数字文字列
  2. number: TeX 内部の整数。\numexpr などで演算できる
  3. counter: \newcounterで定義、\setcounterで更新される

そして、これらを相互に変換する基本的な流れは下記のようになります。

  1. character → number
    • \numexpr <string> \relax
  2. number → character
    • \the <number>
  3. number → counter
    • \setcounter{<number>}
  4. counter → number
    • \value{<counter_name>}
  5. character → counter
    • \setcounter{<string>}
  6. counter → character
    • \arabic{<counter_name>}

ここまで読んでいただき、ありがとうございました。

Discussion