読者です 読者をやめる 読者になる 読者になる

Diary over Finite Fields

515ひかるが書き溜めたメモとコラムと雑記

TeX & LaTeX Advent Calendar 2015 7 日目

この記事は TeX & LaTeX Advent Calendar 2015 の記事です. 昨日 6 日目の記事は tex-ut-tex さんの 【TeX & LaTeX Advent Calendar 2015】 今さらながら otftotfm を使ってみた 【第 6 日目】 で, 明日の担当は senopen さんです.

www.adventar.org

もくじ

eqnarray を使ってはいけないという話

さて私は初心者で, しかも LaTeX を真面目に使い始めたのはわりと最近だったりします. なので, 技術的な基本というよりはみんな知ってるかと思って声高には言わないけど, LaTeX 初心者が指摘されるまで直せないことについて書こうと思います.

それは何かというと, LaTeX 標準で入っている別行立て数式環境 eqnarray を使ってはいけないということです. かわりに amsmath パッケージの align 環境を使いましょう.

上記の事実を知っている方はこの記事を読む必要はありません.*1 まぁおそらくこの企画に参加している人は読む価値はないでしょう……

なぜ使ってはいけないのか

端的に言えば, いろいろと問題があるからです. 奥村先生の 『LaTeX2e美文書作成入門』 によれば,

LaTeX 2.09, LaTeX2e の eqnarray 環境は不完全なので, amsmath パッケージではそれに代わるいくつかの命令を補っています. その代表がこの align 環境です. & の位置で桁揃えします. (中略) eqnarray のように & の位置に余分な余白ができたり数式番号と数式が重なったりしません. (奥村晴彦, 黒木裕介 著, 改訂第6版 LaTeX2e 美文書作成入門, p116, 2013)

とのことです. この eqnarray のように & の位置に余分な余白ができたり数式番号と数式が重なったりしません. という記述から, 逆に言えば eqnarray 環境には & の位置に余分な余白ができたり数式番号と数式がかさなったりするということがわかります.

他にも, TeX Stack Exchange で eqnarray で検索してみると, 解答者の人は異口同音に "Avoid eqnarray" と言っていて, こんな記事も.

tex.stackexchange.com

もとを辿ってみるとこんな雑誌の記事が見つかります.

http://www.tug.org/TUGboat/tb33-1/tb103madsen.pdf

タイトルはまんま, "Avoid eqnarray!" です.

とまぁこの通りパッケージなしで使える eqnarray 環境は嫌われています.*2 しかし嫌われるにはまっとうな理由もあるわけなので, 実際にこの"Avoid eqnarray!"にそって eqnarray の問題点を再現しましょう.

再現

実行環境

 % tlmgr --version
tlmgr revision 38618 (2015-10-12 04:51:38 +0200)
tlmgr using installation: /usr/local/texlive/2015
TeX Live (http://tug.org/texlive) version 2015
 % uplatex target.tex
 % dvipdfmx target.dvi

で PDF を出力しております.

お断り

先に書いておきますが, & の位置に余分な余白ができる という現象は私の環境では再現できませんでした.

検証に使うマクロ

eqnarray 環境の問題をわかりやすくするために, 次のような白い箱を表示するマクロ(横に長さ可変)をつくります. といっても \framebox[横幅の長さ]{1文字分の縦の長さ確保} しているだけです(デフォルトは横幅 3cm).

\newcommand{\dbx}[1][3cm]{\framebox[#1]{\phantom{}}}

f:id:hikaru515:20151206144149p:plain

これを使って検証していきます. ちなみに, マクロ名は Avoid eqnarray! に合わせました.

数式番号と数式がかさなる.

実際にやってみましょう. 比較のために equation 環境と並べてみます.

\begin{equation}
 \dbx = \dbx[12cm]
\end{equation}

\begin{eqnarray}
 \dbx = \dbx[12cm]
\end{eqnarray}

出力はこの通り, equation 環境では数式番号が下にずれているのに対し, eqnarray 環境は数式が数式番号の上に乗ってしまっています.

f:id:hikaru515:20151206145444p:plain

これでは数式番号のタテの位置が揃いません.

もちろん, amsmath の align 環境ではこの点は問題になりません.

%% preamble
\usepackage{amsmath}

%% document
equation,
\begin{equation}
 \dbx = \dbx[12cm]
\end{equation}

eqnarray,
\begin{eqnarray}
 \dbx  = \dbx[12cm]
\end{eqnarray}

align,
\begin{align}
 \dbx  = \dbx[12cm]
\end{align}

f:id:hikaru515:20151206150609p:plain

数式カウンターがひどい

先に言っておきますが, これはひどい.

まず, 相互参照をします.

\begin{eqnarray}
 \dbx &=& \dbx[5cm] \\
  &=& \dbx \label{eq:2}
\end{eqnarray}

(\ref{eq:2}) より, 結論が導かれる.

これは普通に表示されている式番号がでます.

f:id:hikaru515:20151206153649p:plain

ではなんらかの事情で, (5) の式番号を消したとしましょう.

\begin{eqnarray}
 \dbx &=& \dbx[5cm] \\
  &=& \dbx \nonumber\label{eq:2} 
\end{eqnarray}

(\ref{eq:2}) より, 結論が導かれる.

このとき, 期待される出力は (\ref{eq:2}) より の部分が (??) とかになっていて欲しい(要するに \label{eq:2} が undefined であって欲しい) わけです. なので何度タイプセットしても Warning が出ることが想定されるわけですが...

タイプセットしてみます.(whichprop.tex はテストファイルの名前です.)

% uplatex whichprop.tex | grep "Warning"
LaTeX Warning: Reference `eq:2' on page 1 undefined on input line 34.
LaTeX Warning: There were undefined references.
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
% uplatex whichprop.tex| grep "Warning"
(出力なし)

と, 二回目で Warning が消えてしまいました. dvipdfmx して PDF を確認してみると...

f:id:hikaru515:20151206154539p:plain

存在しないはずの式番号 (5) が出てきています(?!) じゃあ次の式番号は何かと実験してみると……

\begin{eqnarray}
 \dbx &=& \dbx[5cm] \\
  &=& \dbx \nonumber\label{eq:2} 
\end{eqnarray}

(\ref{eq:2}) より, 結論が導かれる.

\begin{equation}
  \dbx = \dbx
\end{equation}

f:id:hikaru515:20151206155026p:plain

エーッ, 式番号 (5) に戻ってるぅぅぅぅぅ!?*3

とまぁよくわからないことが起こります. ちなみに, 同じことを align でやってみると,

\begin{align}
 \dbx &= \dbx[5cm] \\
  &= \dbx \nonumber  \label{eq:2}
\end{align}

(\ref{eq:2}) より, 結論が導かれる.

まず, eq:2 が未定義だとちゃんと警告してくれます.

% uplatex whichprop.tex | grep "Warning"
LaTeX Warning: Reference `eq:2' on page 1 undefined on input line 34.
LaTeX Warning: There were undefined references.
% uplatex whichprop.tex | grep "Warning"
LaTeX Warning: Reference `eq:2' on page 1 undefined on input line 34.
LaTeX Warning: There were undefined references.
% uplatex whichprop.tex | grep "Warning"
LaTeX Warning: Reference `eq:2' on page 1 undefined on input line 34.
LaTeX Warning: There were undefined references.
...

この状態で, dvipdfmx しても当然未定義ですので, 期待どおりの出力になります.

f:id:hikaru515:20151206160417p:plain

もうこの事案だけでも, どう考えても align を使うべきであるということが納得していただけると思います. 実際これ何が起きているのかというと, Avoid eqnarray! によれば,

So, even in eqnarray* the equation counter is stepped up, and later stepped down at the end of each line.(http://www.tug.org/TUGboat/tb33-1/tb103madsen.pdf ,p3)

要するに, \nonumber をしてても eqnarray* 環境を使っていても, 式番号は定義されていて,1 行追加するごとにカウンターは 1 増えて, その行が終わるとカウンターを 1 減らすという仕様になっているようです.*4 相互参照しない限り表面化しないバグなわけですが, 誤って式番号がない部分を参照しても Warning さえでないのはさすがに問題でしょう……少なくとも私はそう思います.

ちなみに, 上のような挙動になってるのかを見るために, \theequation という現在の式番号を出力する命令があるようなので, 実際に試してみると,

いま数式番号は \theequation です.

\begin{eqnarray*}
 \text{1行目は}   \theequation\\
 \text{2行目は}  \theequation\\
\end{eqnarray*}

いま, 数式番号は \theequation です.

このコードによる出力は次のようになります:

f:id:hikaru515:20151206161017p:plain

はい. とうぜんこうなります. しかしなんでこうなるのか……

amsthm パッケージの proof 環境との相性

先程のと比べると小ネタですが, amsthm という定理環境のパッケージがあります. 私自身は使わないのですが, 基本的なパッケージですので使う人も多いかと思います. ところで, これには標準で proof 環境が用意されています.

そこで,

\begin{proof}
\dots
\begin{equation*}
 a = 0
\end{equation*} 
\end{proof}

\begin{proof}
\dots
\begin{eqnarray*}
 a =0 
\end{eqnarray*} 
\end{proof}

としてみると, 次のように出力されます.

f:id:hikaru515:20151206162909p:plain

しかし, これではちょっと白抜きの四角が右下過ぎますね. そこで, \qedhere という命令があり, いい感じのところに調整してくれるそうです.

\begin{proof}
\dots
\begin{equation*}
 a = 0 \qedhere
\end{equation*} 
\end{proof}

\begin{proof}
\dots
\begin{eqnarray*}
 a =0 \qedhere
\end{eqnarray*} 
\end{proof}

しかし...

f:id:hikaru515:20151206163126p:plain

だめだこりゃ.

ちなみにこの \qedhere, align 環境でもそのままではうまく行かなくて,

\begin{proof}
\dots
\begin{align*}
 a =0 \qedhere % 正しく出力されない
\end{align*}
\end{proof}

\begin{proof}
\dots
\begin{align*}
 a =0 &\qedhere % いい感じに出力される
\end{align*}
\end{proof}

f:id:hikaru515:20151206164137p:plain

ちなみのこのコードは次の StackExchange からいただきました.*5

tex.stackexchange.com

終わりに

なんというか, 常識を記事にしようという気持ちで始めたのですが, 使ってはいけない理由を掘り下げてみたのは初めてだったので知らないことが多く, 思ったよりもすごく長くなってしまいました. カウンターに関してはほんとうにアレって感じでアレ.

今後もし初心者で eqnarray を使っている人を見かけたら, 特に理由がない限り amsmath パッケージの align 環境を使うように伝えてあげてください. ひょっとしたら案外身近にいるかもしれない……

明日のバトンを回しておきます. 8 日目は senopen さんで, TeXにはまらないためのキホン です.

ではでは.

参考にしたもの

*1:私もまさかとは思ったのですが, 今年に入って eqnarray 環境を使っているマンを複数人観測したので, 私の知り合いはひょっとしたら使っている人が多いのかもしれないなと思いここに書いておくことにします. だからこの記事は Advent Calendar に書いているけど LaTeX 使って初めてもの書く同級生や後輩への記事にもなっています.

*2:CTAN の amsthm のユーザーガイドでは, "unlike eqnarray" というフレーズが 3 回使われて, いくども eqnarray を使うよりも align や gather といった環境を使ったほうがよいと強調されます.

*3:初めてこの現象に遭遇した私の心の声です.

*4:私はカウンターをそもそもどう実装しているのかみたいな話はわからないので, これ以上深い理解はできません.

*5:eqnarray でもうまくやる方法あるのかもしれませんが使わないほうがよいことは確実なので探してません.