第4章  数式

TeXで文章を書く最大のメリットは数式を簡単に書けるということでしょう。Lamuriyanでは数式をMathMLに変換して出力します。

ブラウザでMathMLを表示するには以下のどちらかを利用してください。

  1. MathML対応ブラウザで表示

  2. MathJax利用する

現在ではMathMLへのブラウザの対応状況は悪く、MathJaxを利用するのが無難かと思われます。

4-1章数式の書き方

Lamuriyanでは数式は$数式$,$$数式$$,\[数式\],eqnarray環境,eqnarray*環境を用いることで書くことが出来ます。

4-1.1$数式$形式

$数式$は「 x=y 」の様にインライン形式として出力されます。ここでは大型演算子 などは 01 の様になります。

インラインとブロック形式のHTMLの違いとしては、<math>にdisplay="block"属性が付くか付かないかの違いしかありませんが。

4-1.2$$数式$$形式

$$数式$$はブロック形式の数式として出力されます。

x+y

の様になります。\[と\]はLamuriyanではどちらも$$に置換されるだけなので、実際には\[数式\[の様に書いても数式と判断されます。これ豆な(-_-)

ここでは などの大型演算子は

01

の様に上下につきます。

4-1.3eqnarray環境

TeXと同じように、数式に番号を付けることが出来、数式の位置揃えが出来る環境です。

  1. \begin{eqnarray}
  2.   \label{eq:微分の定義}
  3.   \frac{df(x)}{dx} &=&\lim_{\delta x\to0}\frac{f(x+\delta x)-f(x)}{\delta x}\\
  4.   \label{eq:偏微分の定義}
  5.   \frac{\partial f(x,y,z...)}{\partial x}&=&
  6.   \lim_{\delta x\to0}\frac{f(x+\delta x,y,z,...)-f(x,y,z,...)}{\delta x}
  7. \end{eqnarray}
(4:1-1) df(x) dx = lim δx0 f(x+δx)-f(x) δx (4:1-2) f(x,y,z...) x = lim δx0 f(x+δx,y,z,...)-f(x,y,z,...) δx

一つ目の要素は右寄せ、二つ目は中央寄せ、三つ目は左寄せになります。本家TeXと違って、Lamuriyanの表はいくらでも拡張可能なので、三つ以上&があっても、問題なく表示されます。その際、位置揃えは(たぶん)中央寄せになります。

デフォルトでは数式の番号は(チャプター番号:セクション番号-セクション内での式の番号)になります。チャプター番号とセクション番号が0の時はそれぞれ省略されます。これらの設定を変更したい場合は\theeqnumberを書き換えてください。全部の行で式番号が要らない場合はeqnarray*環境を用いてください。

\nonumberを用いることで、その行の数式は書かれないようになります。

f(x) = x100 + x99 + x98 + x96 +.............. (4:1-3) ...................+ x3 + x2 +x+1

4-2章array環境

行列などの表組の数式を書きたい場合に使います。TeXと同様\begin{array}{crl}の様に使います

  1. $$
  2. A = \left(
  3.   \begin{array}{ccc}
  4.     1 & 0 & 0\\
  5.     0 & 1 & 0\\
  6.     0 & 0& 1
  7.   \end{array}\right)
  8. $$
A= 1 0 0 0 1 0 0 0 1

4-2.1array環境における縦線横線について

\hlineや環境の引数の|には現在対応していません。というのも、MathMLの仕様についてよく理解してないからです。( ^ω^)ゴメンネ

4-3章MathJaxを使う問題点

\labelを宣言すると、該当ノードにIDを設定し\refではそのIDにリンクを張る仕様になっていますが、MathJaxを使うと、数式中で定義したIDが消えてしまい、リンク先がなくなってしまう問題があります。

通常の\refを用いて書くと、リンクが生成されてしまうので、\nolinkrefを用いるか、convsetting.hcvのconvert項目のRefLabelConverterのオプションにmlabeledtrを追加してください。\nolinkrefを用いるとこれ単体がリンクを使わない参照になります。後者のコンバーターの設定を用いると、\refを用いても、\refが付くノードの名前が引数に一致した場合は、リンクを使わない参照を作るようにします。デフォルトではこの設定が付いていますので、数式への参照はリンクが生成されません。MathJaxは使わないので、数式へのリンクが生成されて欲しい場合は、
 
reflabel>nodamushi.ntex.html.RefLabelConverter:mlabeledtr,math
 
という設定の後ろにある「mlabeledtr,math」を削除してください。

4-4章数式モードで使える実体参照

ひらく様の ひらくの工房-TeX_mathml.rb に載っている記号については、参考という名の丸コピいたしました。これ書いてるときにページ見てて気がついたのですが、別ページにまだいっぱい作ってない記号が載っていました。ぶっちゃけ、これ作った本人が lim ぐらいがあれば何も問題ないというゴミ屑なので、面倒くさいので放置です( ^ω^)

4-4.1足りない実体参照を自作する

あの実体参照がないとか、人を馬鹿にしてんじゃねーぞ死ねnodamushi!!という事が多分にあるでしょう。その意見にはおおむね賛成ですが、何も貴方が犯罪者になる必要はありません。自分で定義しましょう。

実体参照もマクロを使って定義しています。そのためのマクロが\mathescapeです。

\mathescape#1#2,#3という構文で、#1は登録するコマンドシーケンス名を、#2は実体参照の文字列を、「,」を挟んで#3は<mo><mi><mn><mtext>のどれでくくるかの指定をします。指定には以下の一文字を使います。

第三引数

説明

o,O

<mo>で囲みます。+や-や(などの演算子に付けます

n,N

<mn>で囲みます。数値を表します

t,T

<mtext>で囲みます。文字列を表します。

i,I

<mi>で囲います。xとかyとか基本的に何でも<mi>には入るみたいです。

a,A

<mi>で囲います。i,Iと違い、mathvariant=normalの属性がつきます。

なんでa,Aかって?nodamushiの語学力のなさが原因だよ。何も思いつかなかったからアルファベットの最初でいいやってだけだよ(-_-)

大文字と小文字の違いは、大文字の場合

010

の様に上下に付くようになります。
 

では、実際に定義をしてみましょう。実体参照には&と#の文字があって、そのままだと毎回\&,\#と書かないといけません。これは面倒ですのでこれらのカテゴリコードを通常の文字列に変更してしまいましょう。他の範囲に影響を出さない為にグループで囲っておきます。

  1. \bgroup
  2. \catcode `\&=12
  3. \catcode `\#=12
  4. \global\mathescape\sum &sum;,O
  5. \egroup

4-5章関数、演算子を定義する

\mathescapeでも定義できますが、一箇所使うだけだってのに、いちいち定義なんてしてらんない、って時には\operatornameを使いましょう。これはTeXと動作は一緒で、関数を定義するときに使います。

  1. \[
  2. {arg\,max}_{x\in X}\text{}\operatorname*{arg\,max}_{x\in X} sin^2\text{}\operatorname{sin}^2
  3. \]
arg max xX arg max xX  si n2 sin2

演算子の場合は\mathbin,\mathopが使えます。

4-6章マクロに関して

\over,\under,\frac,\sqrt,\textなど、基本的な物は最初から実装してあります。

4-6.1 Pm n とかの前後に付く記号を書きたい

\sidesetを使うことが出来ます。

  1. \[
  2. \sideset{_n}{_m}{P}
  3. \]
Pm n

4-6.2<mmultiscripts>を書きたい

\multiscriptsを使うことが出来ます。このマクロは

#4  #5
  #1
#2  #3

の様な配置になります。何も表記したくない場所は\noneNodeと記入してください。

  1. \[
  2. \multiscripts{M}\alpha\noneNode{\beta+1}\omega
  3. \]
M ω α β+1

4-6.3<menclose>の角丸や円を書きたい

\roundedbox,\circleが使えます。書式は\roundedbox[#1]#2です。第一引数は<menclose>の属性を,区切りで並べます。(id=rbox,class=rboxclassの様に)。第二引数は<menclose>の中身です。

  1. \[
  2. \roundedbox{x} \circle{y}
  3. \]
x y

4-6.4数式に打ち消し線を書きたい

\cancelが使えます。書式は\cancel[#1]#2です。第一引数はu,v,h,dのうちいずれか一文字を選択してください。省略した場合はuになります。実装は<menclose>の~strikeを使っています。第一引数も、これの一文字目です。

  1. \[
  2.   \frac{1}{\cancel{(a+b)}}\frac{\cancel[d]{(a+b)}}{\cancel[h]{x}}\cancel[v]{x}
  3. \]
1 (a+b) (a+b) x x

4-6.5ていうか、<menclose>書きたい

\encloseが使えます。書式は\enclose[#1]#2#3です。第一引数は<menclose>の属性を,区切りで並べます。第二引数は<menclose>のnotation属性を指定します。第三引数は<menclose>の中身です。

  1. \[
  2. \enclose{actuarial}{a^2+b^2}
  3. \]
a2 + b2

4-7章自作マクロについて

ここに書いてない機能については、自作マクロを作成するしかありません。

数式モードでマクロは基本的には\boxと\mfragと\setAttr,\setAttrsを駆使してDOMを生成していくことで作ります。

これらはLamuriyanにおける他のマクロの作り方(今度書く)と同様ですが、いくつか特殊なルールがあります。

4-7.1<mrow>で囲うべきか判断できない場合

MathMLにおいて、<mrow>は様々な場面で使われる。例えば、<msup>などは二つの要素を持つが、中に数式を入れたい場合は
 
<msup><mrow><mo>(</mo><mi>x</mi><mo>+</mo><mn>1</mn><mo>)</mo></mrow> <mn>2</mn></msup>
 
といった具合に<mrow>で囲う必要がある。しかし、後ろの<mn>2</mn>は要素が一つしかないので、<mrow>で囲う必要性はない。むろん、囲っても構わないのだが、美しくない。要素が一つなら<mrow>で囲わないのがジャスティスである。しかし、これからいくつの要素が入るかなんてマクロ実行段階で知る術はない。

そこで、Lamuriyanでは数式モードにおいて特殊なタグ<mfrag>というタグを定義している。このタグは要素が一つしかない場合はDocumentFragmentとして働き、要素が二つ以上あるときは<mrow>になるというタグだ。\mfrag#1マクロで<mfrag>を生成できる。後は#1の部分に中身を書けば良い。

4-7.2スコープの為のグループは作らない

Lamuriyanでは数式モードにおいて、begingroupフックを利用している。グループの中身を 4-7.1章 にて説明した<mfrag>で囲う命令を発効する為である。こうしなければ、{x+1}^2が<mi>x</mi><mo>+</mo><msup><mn>1</mn><mn>2</mn></msup>となってしまうからである。

そこで、Lamuriyanでは{でグループが作られるたびに(マクロの引数のグループは関係ない)設定したトークンをアウトプットするeverybegingroupというフックを用意し、これを解決した。しかし、これが逆にマクロを作る上で問題となることがある。

例えば、引数をそのまま{#1}と書き出した場合、この{に反応して

生成される。それは意図した挙動でないことが多いだろう。したがって、数式モードで使うマクロでは{}を用いてグループを作らないことが賢明である。

それでもグループが必要な場合には、\bgroup,\egroupのペアを用いる。数式モードでは\bgroup,\egroupはeverybegingroupのフックが呼び出されない。

4-7.3ある範囲を一つの<mo><mi><mn><mtext>にしたい

Lamuriyanは数式モードにおいて、\@startchargroupコマンドが発行されてから、\@endchargroupが現れるまでの間を一つの<mo><mi><mn><mtext>と認識します。\@startchargroupの引数は「o,i,n,t」のいずれか一文字です。それぞれ、<mo><mi><mn><mtext>に対応しています。\mathopや\operatorなどはこれを利用しています。

4-7.4^_を上下につけるか横に付けるかを変更する

あるノードに対して^_の位置はそのノードに対して\@underoverflagが呼ばれているかどうかで決まる。

  1. \box{nodename}{\@underoverflag 内容}

の様に書くとこの<nodename>は上下に^_が付く。