MathJax を使う

作成日:2013-11-24
最終更新日:

MathJax による表現

最近この数年はASCIIMathMLを使い続けてきた (最近は ASCIIMath となっている。この名前の違いの理由はそれぞれのページをみてほしい)。 一方、ASCIIMathML のオリジナルの数式表現は LaTeXMathML を使った場合に比べて数式が美しくないと思っていた。 いっぽう、Web での数式表現は MathJax がいいということは聞いていたが、 LaTeX の表現でしか使えないと思い込んでいて、ろくに調べずにいた。 ところが今日、MathJax でも ASCIIMathML の表記法(である ASCIIMath )が使えることがわかった。試してみると数式が美しい。 すなわち、MathJax では LaTeX だけでなく、 ASCIIMathML の表記も理解してMathJax 固有の表示をすることができる。さっそく乗り換えることにした。

MathJax (www.mathjax.org) のページは英語である。 なお、2019 年になって、MathJax3 が公開された。これについてはリンク先を参照してほしい。

MathJax の使い方

ASCIIMathML は自前で js ファイルを持ってきたが、 MathJax はリモートにあるサーバを使うのがよさそうだ。 これには、<head> と </head> の間で、次の行を書けばよい。

<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TEX-MML-AM_CHTML"></script>

ここで、mathjax と MathJax.js の間にあるバージョン番号 x.y.z は徐々に変わっているから、適宜直さないといけない。

なお、以前は次のように cdn.mathjax.org 配下であったが、今は上記のドメインに移っている。

<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TEX-MML-AM_CHTML"></script>

ASCIIMath の表現で式が書ける。以下、対比してみよう。 なお、文字入力の事例は、福井高専の MathMLマニュアル (toshichan.be.fukui-nct.ac.jp)から、 4章の MathML Tips 集による。 ただし、ASCIIMath 入力における前後のバッククォーテーションや、 LaTeX 入力における前後の \( \) (インラインモード)や $$ $$ (ディスプレイモード)は省略している。

なお、MathJax は、Mozilla/Firefox 系 や Opera, Safari, Google Chrome のブラウザで表示できたことを確認した。

事例の対比:基本編

文字入力 (ASCIIMath 入力)表現説明備考文字入力 (LaTeX 入力)
a+b+3`a+b-3`加法、減法
a b`a b`乗法
1/2+1/x-x/3`1/2+1/x-x/3`除法\frac{3}(x)
(a+b)-3`(a+b)-3`カッコ
(x-1)/3+1/(a+b)-(x+3)/(x-c)`(x-1)/3+1/(a+b)-(x+3)/(x-c)`分数と式
x^2-3^x`x^2-3^x`べき乗
sqrt(x)+sqrt(2)`sqrt(x)+sqrt(2)`根号
a=b`a=b`等号
a gt b`a gt b`不等号
a ge b`a ge b`等号つき不等号
a lt b`a lt b`不等号
a le b`a le b`等号つき不等号
f(x)`f(x)`関数
x^(y-1/3)`x^(y-1/3)`分数のべき乗
root(3)(x)+root(a)(3)`root(3)(x)+root(a)(3)`平方根、n 乗根
sin(x+3)`sin(x+3)`三角関数
pi`pi`円周率
log_3(x)`log_3(x)`対数下添字log_{3}(x)
log_e(x)+e^x`log_e(x)+e^x`自然対数
sin^-1(x)`sin^-1(x)`逆三角関数
sum_(i=1)^20k_i`sum_(i=1)^20k_i`数列の和
prod_(i=1)^20k_i`prod_(i=1)^20k_i`数列の積
$$ \coprod_{b}^{a} $$直和分割\coprod_{b}^{a}
{::}_(\ n)C_r`{::}_(\ n)C_r`組み合わせの数ダミーの囲みを作ってその右側として表した文字を左側添字とする
{::}^(\ t)A`{::}^(\ t)A`行列の転置同上
vec v`vec v`矢線ベクトル
(a_x,a_y+b_y)`(a_x,a_y+b_y) `成分ベクトル
((x,3),(1,y))`((x,3),(1,y)) `行列
|(x,3),(1,y)|`|(x,3),(1,y)| `行列式
dy/dx`dy/dx`微分
intf(x)dx`intf(x)dx`不定積分\intf(x)dx
int_0^1f(x)dx`int_0^1f(x)dx`定積分\int_0^1f(x)dx
int_1^oo1/x^2dx`int_1^oo1/x^2dx`無限大
abs(-x)`abs(-x)`絶対値
norm(x)`norm(x)`ノルム
lim_(x->0)sin(x)`lim_(x->0)sin(x)`極限
4+3i`4+3i`虚数
(delz)/(delx)`(delz)/(delx)`偏微分\frac{\partial{z}}{\partial{x}}
(d^2y)/dx^2`(d^2y)/dx^2`2 階微分
|\ |`|\ |`半角スペース
|quad|`|quad|`半角 * 2 スペース
a times b`a times b`乗算旧来の a XX b は使えない
a div b`a div b`除算旧来の a -: b も使える

事例の対比:応用編

下記は、基本編以外の記号である。

文字入力表現説明文字入力 (LaTeX 入力)
bbA bba`bbA bba`太字
$ \boldsymbol{Aa} $太字イタリック\boldsymbol{Aa}
bbbC bbbN bbbQ bbbR bbbZ`bbbC bbbN bbbQ bbbR bbbZ`二度打ち体
ccA ccB ccC ccE ccF ccH ccI ccL ccM ccR ccS`ccA ccB ccC ccE ccF ccH ccI ccL ccM ccR ccS`スクリプト体
$ \mathcal{ABCEFHILMRS} $カリグラフ体\mathcal{ABCEFHILMRS}
frA frB frC frH frI frR frZ`frA frB frC frH frI frR frZ`フラクトゥール
sfA sfa`sfA sfa`サンセリフ
ttA tta`ttA tta`テレタイプ
dotA dota`dotA dota`(時間に関する)一階微分
ddotA ddota`ddotA ddota`(時間に関する)二階微分
|__x__|`|__x__|`床関数。実数 `x` に対する `x` 以下の最大の整数
|~x~|`|~x~|`天井関数。実数 `x` に対する `x` 以上の最小の整数
nn`nn`集合の交わり
nnn`nnn`集合の交わり。(`sum` のように添字集合とともに用いる)
uu`uu`集合の結び
uuu`uuu`集合の結び。(`sum` のように添字集合とともに用いる)
sub`sub``A sub B` : `A` は `B` に含まれる\subset
sup`sup``A sup B` : `A` は `B` を含む
x in X`x in X``x in X` : `x` は `X` の要素である
x notin X`x notin X``x notin X` : `x` は `X` の要素でない
underset(y in C)(min) norm(x - y)`underset(y in C)(min) norm(x - y)`最小値

ASCIIMath + MathJax による証明の一例

せっかくなので、ASCIIMath 記法と MathJax による表示によって数学の一証明を記述してみる。 題材は、`pi` が無理数であるという証明である。この証明は、 大阪理工大学(現:近畿大学)の学生であった岩本義和(湯上義和)氏による。 これを真鍋和弘氏(札幌篠路高校)が、 http://www7a.biglobe.ne.jp/~watmas/dosukyo/circle-reports/irrationalnumberbyManabe.pdf にてこの証明を紹介している。これを多少追記して記述してみる。

定理1

`pi` は無理数である。

補題1

`pi^2` が無理数ならば、`pi` は無理数である。

証明

`pi` が有理数ならば、`pi^2` は有理数である (仮に `pi = a/b` という形の有理数ならば、`pi^2 = (a^2)/(b^2)` という形の有理数になる)。 この対偶をとれば、補題1が得られる。

補題2

次の関数 `f(x)`
`f(x) = x^n (1-x)^n / (n!) , n in NN`
は、次の3つの性質を満たす。

  1. `f(x) = 1/(n!) sum_(m=n)^(2n)c_m x^m` という多項式であり、係数 `c_m` はすべて整数である。
  2. ` 0 lt x lt 1` に対して `0 lt f(x) lt 1/(n!)`
  3. `AAk( gt 0)` に対して、関数 `f` の `k` 回微分 `f^((k))(x)` を考える。 `x` が 0 と 1 のときの微係数 `f^((k))(0)` と `f^((k))(1)` はいずれも整数である。

証明

  1. `f(x) = x^n (1-x)^n / (n!) = x^n / (n!) (1-x)^n = x^n / (n!) sum_(m=0)^n ({::}_(\ n)C_m(-x)^(n-m)) = 1/(n!) sum_(m=n)^(2n) ((-1)^(m-n){::}_(\ 2n)C_m)x^m `
    ここで、`{::}_(\ n)C_m` は2項係数であるから証明された。
  2. `0 lt x lt 1` では `x^n lt 1 ` かつ ` (1-x)^n lt 1` 。よって `f(x)` の式から成り立つ。
  3. `x = 0` のときを考える。`k < n` であれば、`f^((k))(x)` の定数項はないから、`f^((k))(x) = 0`。 `k gt 2n` であれば、`f^((k)) = 0` であるから `f^((k))(x) = 0` 。`n lt k le 2n` のときは、1. から `f^((k))(0) = (k!)/(n!) c_k` であるが、`k > n` だから `(k!)/(n!)`は整数。かつ `c_k` は 1. より整数である。したがって、`f^((k))(0)` は整数である。
    `x = 1` のときを考える。`f(x) = f(1-x)` が恒等的に成り立つから、`f^((k))(1-x) = (-1)^kf^((k))(x)` である。 よって、`f^((k))(1) = (-1)^(k)f^((k))(0)` であり、i で証明した `f^((k))(0)` が整数であることと合わせ、 `f^((k))(1)` も整数である。

補題3

任意の正の実数 `c` に対し、十分大きな整数 `n` をとれば、`(c^n) / (n!)` はいくらでも小さくすることができる。

証明

正の整数 `m` を `m > 2c` となるようにとる。すると `c / m < 1 / 2` であるから、 `n` を `m` より大きい整数とすれば、

`(c^n) / (n!)` ` = (c * c * * * c) / (1 * 2 * * * m) * (c / (m + 1)) * (c / (m + 2)) * * * c/n`
` lt (c^m) / (m!) * c/m * c/m * * * c/m`
` lt (c^m)/(m!) * 1/2 * 1/2 * * * 1/2 `
` = (c^m)/(m!) * (1/2)^(n-m)`

ここで、`n` を大きくすれば `(1/2)^(n-m)` はいくらでも小さくすることができる。

定理1の証明

`pi^2` が有理数と仮定すれば、正の整数 `a, b` によって `pi^2 = a / b` とおける。補題 2 の関数から、 新しい関数 `F(x)` をつぎのように作る。

`F(x) = b^(n)[pi^(2n)f(x) - pi^(2n-2)f^((2))(x) + pi^(2n-4)f^((4))(x) - ... + (-1)^(n)f^((2n))(x)]`

このとき、各行を展開すると `F(0)` は整数であることがわかる。なぜなら、[] 内を展開すると、 第1項は `b^(n)pi^(2n)f(0) = b^n (a/b)^n f(0) = a^n f(0)` となり、`f(0)` は補題2のiiiで整数となるからである。以下、第2項、第3項も同様にして展開し、 すべての項が整数であるから、`F(0)` は整数である。同様に、`F(1)` も整数である。さて、 `F(x)` の `x` に関する 2 回微分は

`(d^2)/(dx^2) F(x) = b^(n)[pi^(2n-2)f(x) - pi^(2n-4)f^((2))(x) + pi^(2n-6)f^((4))(x) - ... + (-1)^(n-1)f^((2n))(x)]`

となる(なお、`f(x)` は `x` の `2n` 次式だから、`f^((2n+2)) = 0` である) 。これと `F(x)` の元の式から

`(d^2)/(dx^2) F(x) = F^(′′)(x)= -pi^2F(x)+b^n pi^(2n+2) f(x)`

となる。また、

`d/(dx)[F^(')(x)sin pi x - pi F(x) cos pi x]``=[F^('')(x)+ pi^2F(x)] sin pi x`
`=b^n pi^(2n+2)f(x) sin pi x`
`=pi^2 a^2 f(x) sin pi x`

となるので

`alpha = pi int_0^1 a^n f(x) sin pi x dx`` = [1/pi F^'(x) sin pi x - F(x) cos pi x]_0^1 `
` = F(0) + F(1)`

は整数となる。一方、補題2の ii より、

` 0 lt pi int_0^1 a^n f(x) sin pi x dx lt (pi a^n)/ (n!)`

となる。したがって、十分大きな n に対して、

`0 < alpha < (pi a^n)/(n!) < 1`

となる(補題3も参照)。`alpha` は整数であったからこれは矛盾である。 よって `pi^2` は無理数であり、補題1より `pi` もまた無理数である。■

解析学の紹介の次は代数学といきたいが、現代日本人の業績は知らない。 江戸時代の和算家、 関孝和が導いた結果を応用数理学会誌の読後感として書いたので、 そちらを参照されたい。

スクリプト体とカリグラフ体

カリグラフ体はスクリプト体と微妙に違うらしい。ただし、ASCIIMathML のオリジナル js ファイルや、 MathJax で AM_CHTML モードを使う限りにおいて、スクリプト体は表示できない。 両者を使い分けるには、MathJax で TEX_MML_AM_CHTML モードにしないといけないようだ。

文字入力表現説明
`ccL`
`ccL`スクリプト体
$ \mathcal{L} $
$ \mathcal{L} $カリグラフ体

MathJax による AsciiMath のサポート

以下は、http://docs.mathjax.org/en/latest/asciimath.html (MathJax AsciiMath Support) の拙訳である。

AsciiMath の MathJax によるサポートは2部分からなる: asciimath2jax プリプロセッサとAsciiMath インプットプリプロセッサである。 前者は `...`で囲まれた部分のようなウェブページの数式部分を探し、 MathJax によるその後の数式処理のための目印を付ける。 後者は AsciiMath 記法を MathJax の内部フォーマットの変換するためのものであり、 MathJax のアウトプットプロセッサの一部であるとともにウェブページに表示する。

The support for AsciiMath in MathJax consists of two parts: the asciimath2jax preprocessor, and the AsciiMath input processor. The first of these looks for mathematics within your web page (indicated by delimiters like `...`) and marks the mathematics for later processing by MathJax. The AsciiMath input processor is what converts the AsciiMath notation into MathJax’s internal format, where one of MathJax’s output processors then displays it in the web page.

AsciiMath の入力 jax は実際にはASCIIMathML.js のコピー自身を含んでいる (詳細は AsciiMath home page を見よ)。 この意味は、MathJax の AsciiMath 処理の結果は実際のASCIIMathML.js パッケージを 使った結果と同じになること(少なくともプロセッサが生成した MathML コードに関する限り)が要請されているからである。 David Lippman には以下の点で感謝する。 AsciiMath プリプロセッサの初期バージョンや入力 jax を書いてもらったこと、そして AsciiMath コミュニティからの改善を続けてくれたこと。

The AsciiMath input jax actually includes a copy of ASCIIMathML.js itself (see the AsciiMath home page for details). This means that the results of MathJax’s AsciiMath processing should be the same as using the actual ASCIIMathML.js package (at least as far as the MathML that it generates is concerned). Thanks go to David Lippman for writing the initial version of the AsciiMath preprocessor and input jax and for the ongoing improvements from the AsciiMath community.

asciimath2jax プリプロセッサは、数学デリミタとして、 ページ作成者が使いたいマーカーであれば何でも使えるように変更することができる。 asciimath2jax configuration options (docs.mathjax.org) を見れば、 asciimath2jaxの動作をカスタマイズする方法の詳細がわかる。

The asciimath2jax preprocessor can be configured to look for whatever markers you want to use for your math delimiters. See the asciimath2jax configuration options section for details on how to customize the action of asciimath2jax.

AsciiMath 入力プロセッサは作成者の数学記法を MathJax 内部フォーマット(本質的には MathML)に変換する。 AsciiMath 入力プロセッサにはほとんどコンフィギュレーションオプションがない(詳しくは AsciiMath options セクションを見よ)。

The AsciiMath input processor handles conversion of your mathematical notation into MathJax’s internal format (which is essentially MathML). The AsciiMath input processor has few configuration options (see the AsciiMath options section for details).

AsciiMath 入力 jax が扱えるのはオリジナルの ASCIIMathML 記法(ASCIIMathML v1.4.7) だけであり、 ASCIIMathML の 2.0 で追加された拡張 LaTeXML 記法には対応していない。 にもかかわらず、AsciiMath 入力 jax は AsciiMath が処理するシンボルを定義するテーブルを公開し、 追加シンボルを含むことができるよう拡張可能としている。 一般には、MathJaxのTeX入力jaxを使用してLaTeX表記を処理する方がよいだろう。

The AsciiMath input jax handles only the original ASCIIMathML notation (from ASCIIMathML v1.4.7), not the extened LaTeXMathML notation added in version 2.0 of ASCIIMathML, though the AsciiMath input jax does expose the tables that define the symbols that AsciiMath processes, and so it would be possible to extend them to include additional symbols. In general, it is probably better to use MathJax’s TeX input jax to handle LaTeX notation instead.

AsciiMath デリミタ(delimiters)

デフォルトでは、asciimath2jax のプリプロセッサが AsciiMath フォーマットの数学表現として規定しているのは、 バッククォーテーション(`)である。 $...$ をデリミタとしてはいない。 この理由は、ドル記号が非数学文で非常に多くあらわれるからであり、 これが数学文として扱われると予期せぬ不都合が生じる。 たとえば、単独のドル記号がデリミタ―とすると、 「最初の価格は$ 2.50、追加のコストは$ 2.00」という文では、「 2.50、追加のコストは」という句がデリミターの間にあるため数学表現として扱われる。 このため、AsciiMath 表記に単独のドル記号を使う場合は、設定で明示的に有効にする必要がある。

By default, the asciimath2jax preprocessor defines the back-tick (`) as the delimiters for mathematics in AsciiMath format. It does not define $...$ as math delimiters. That is because dollar signs appear too often in non-mathematical settings, which could cause some text to be treated as mathematics unexpectedly. For example, with single-dollar delimiters, ”... the cost is $2.50 for the first one, and $2.00 for each additional one ...” would cause the phrase “2.50 for the first one, and” to be treated as mathematics since it falls between dollar signs. For this reason, if you want to use single-dollars for AsciiMath notation, you must enable that explicitly in your configuration:

MathJax.Hub.Config({
  asciimath2jax: {
    delimiters: [['$','$'], ['`','`']]
  }
});

ドル記号は頻繁に TeX フォーマットで使われることに注意しておこう。 だから、MathJax のデリミタにドル記号を使うことも避けるべきだ。 ドル記号は TeX 記法のためにとっておくのがいいだろう。

Note that the dollar signs are frequently used as a delimiter for mathematics in the TeX format, and you can not enable the dollar-sign delimiter for both. It is probably best to leave dollar signs for TeX notation.

asciimath2jax プリプロセッサのために新たな設定パラメータを追加したいのであれば、 config/default.js ファイルか、または asiimath2jax configuration options 頁を見よ。 プリプロセッサは MathJax のコンポ―ネントであり、ページ内の AsciiMath 記法を決めている。 AsciiMath notation within the page.

See the config/default.js file, or the asiimath2jax configuration options page, for additional configuration parameters that you can specify for the asciimath2jax preprocessor, which is the component of MathJax that identifies AsciiMath notation within the page.

AsciiMath in HTML documents

AsciiMath の構文が記述されているのは ASCIIMathML syntax pageである。

The AsciiMath syntax is descibed in the ASCIIMathML syntax page.

覚えておいてほしいのは、作成者の数学部分は HTML 文書の一部であるということ、 そのため HTML 文書のマークアップが一部で使われることに気付いてほしい、ということだ。 数学デリミタ内で HTML タグは<BR> は除いて)使ってはいけない。 理由は、AsciiMath フォーマットされた数学文書は HTML タグを含まないからだ。 また、数学表記は最初はページのテキストとしては与えられていないので、 数学表記がブラウザからはHTMLタグのように見えないように注意する必要がある(MathJax が数学表記かどうかを判断する前にブラウザがページを解析する)。 特に、「大きい」記号や「小さい」記号 (<>)、 アンド記号 ( & ) はブラウザにとって特別な意味を持つ。 たとえば、

Keep in mind that your mathematics is part of an HTML document, so you need to be aware of the special characters used by HTML as part of its markup. There cannot be HTML tags within the math delimiters (other than <BR>) as AsciiMath-formatted math does not include HTML tags. Also, since the mathematics is initially given as text on the page, you need to be careful that your mathematics doesn’t look like HTML tags to the browser (which parses the page before MathJax gets to see it). In particular, that means that you have to be careful about things like less-than and greater-than signs (< and >), and ampersands (&), which have special meaning to the browsers. For example,

... when `x<y` we have ...

と書くと問題を引き起こす。なぜならブラウザは <yy という名前から始まるタグとして読み込み始めるからだ (たとえそのようなタグが HTML にないとしても)。 このようなことが起こると、ブラウザはこのタグはドキュメント内で次の > まで (典型的にはその HTML ファイルの次の実際に使われるタグの最後まで)読み通した結果、 作成者が文書テキストの一部が欠けていることに気付く。 この例では、 the “we have ...” 以降は表示されないだろう。なぜなら、ブラウザは<y で始まるタグの一部と考えるからだ。 これは、制作者がこの問題を特定できる使える指標である。 よくあるエラーであり、避けるべきである。

通常、シンボルの両隣にスペースを配置すればこのようなことは避けられる。つまり、

will cause a problem, because the browser will think <y is the beginning of a tag named y (even though there is no such tag in HTML). When this happens, the browser will think the tag continues up to the next > in the document (typically the end of the next actual tag in the HTML file), and you may notice that you are missing part of the text of the document. In the example above, the “we have ...” will not be displayed because the browser thinks it is part of the tag starting at <y. This is one indication you can use to spot this problem; it is a common error and should be avoided.

Usually, it is sufficient to simply put spaces around these symbols to cause the browser to avoid them, so

... when `x < y` we have ...

とすればうまくいく。 別の方法はブラウザがタグと解釈しないように HTML のエンティティ &lt;&gt;&amp; を使うことである。MathJax はこれらを解釈する。すなわち、

should work. Alternatively, you can use the HTML entities &lt;, &gt; and &amp; to encode these characters so that the browser will not interpret them, but MathJax will. E.g.,

... when `x &lt; y` we have ...

MathJax がテキストを解釈する前にブラウザがテキストを解釈することを忘れないように。

Keep in mind that the browser interprets your text before MathJax does.

実例:筆算による割り算

12 16 192 12 72 72 0

参考

まりんきょ学問所コンピュータの部屋マーク付け言語手習い > MathJax を使う


MARUYAMA Satosi