数式評価ツール

数式を入力するとすぐに結果が得られます。ラジアン/度の三角関数、対数、階乗、定数、完全な演算子優先順位に対応しています。

紙に書くのと同じように式を書いてください。 パーサーは入れ子の括弧、単項マイナス、階乗、関数呼び出しを正しい優先順位で処理します。したがって 2 + 3 * 4 は 14、-3^2 は -9 となり、数学の慣例どおりです。

対応している構文

演算子
+ - * / % ^ ! ( )
定数
pi e tau phi inf
三角関数
sin cos tan asin acos atan sinh cosh tanh
一般関数
sqrt cbrt abs sign exp ln log log2 round floor ceil trunc
多引数関数
min max hypot sum avg pow

式が数値になるまで

優先順位こそが問題のすべて

2 + 3 * 4 を読むには、乗算が加算より強く結合することを知っている必要があります。だから答えは 20 ではなく 14 です。すべての演算子は優先順位と結合性を持ちます。乗算・除算・剰余は加算・減算より上位にあり、べき乗はそれらすべてより上位で右結合です。したがって 2^3^22^(3^2) を意味し、64 ではなく 512 になります。

微妙なのが単項マイナスです。数学の慣例ではべき乗より下位に置かれるため -3^2 は -9 になります。指数は 3 に作用し、符号反転はその結果に作用するからです。表計算ソフトはこれに異を唱えることで有名で 9 を返します。同じ式に対して 2 つのツールが違う答えを出す場面を見たことがあるなら、たいていこれが理由です。この評価ツールは数学の慣例に従います。

括弧はこれらすべてを上書きしますし、遠慮なく使う価値があります。優先順位表を引かないと読めない式は、いずれ必ず誤読される式です。

操車場アルゴリズムの概略

式はまずトークン——数値、名前、演算子、区切り記号——に分解され、次に Dijkstra の操車場アルゴリズムによって、演算子がオペランドの後に来る後置形式へ並べ替えられます。2 + 3 * 42 3 4 * + になります。後置形式には括弧も優先順位規則も不要です。トークンの順序が既に構造を表しているため、単純なスタックマシンが 1 回の走査で評価できます。

このアルゴリズムは出力リストと演算子スタックの 2 つを保持します。数値は直接出力へ送られ、演算子は自身を積む前に、同等以上に強く結合するスタック上の演算子をすべて取り出します。括弧はスタック上の目印として働き、閉じ括弧は対応する開き括弧まですべてを取り出します。関数呼び出しは引数カウンタを持つ演算子として同じ流れに乗り、カンマを見るたびにカウントが増えます。

これは表計算エンジンやクエリプランナーの内部でも使われている技術です。線形時間で動作し、再帰も不要で、不正な式も自然に検出できます。最後にスタックがきれいに空にならなければ、入力が釣り合っていなかったということです。

浮動小数点について正直に

結果は IEEE 754 倍精度で計算されます。これはすべてのブラウザと大半のプログラミング言語が使う演算と同じものです。数値は 2 進数で保持され、0.1 のような 10 進小数には厳密な 2 進表現が存在しません。0.1 + 0.2 が 0.3 ではなく 0.30000000000000004 になるのはこのためです。

表示を決まった有効桁数に丸めれば、内部の値を変えずにこのノイズを隠せます。ここの精度コントロールがしているのはまさにそれです。12 に設定すれば読みやすさを保ちつつ、倍精度が実際に区別できる 15〜17 桁まで十分な余裕が残ります。

覚えておくべき限界が 2 つあります。整数が厳密なのは 2^53 までなので、非常に大きな階乗や積はずれていきます。170! を超えるとそのまま無限大へオーバーフローします。もう 1 つ、ほぼ等しい 2 数の引き算は精度を破壊します。上位桁が打ち消し合い、ノイズを含む下位桁だけが残るためです。その引き算を避けるように式を組み替えると、素直な書き方よりはるかに正確になることがよくあります。

オープンソースに関する注記:バニラ JavaScript で実装。サードパーティライブラリは使用していません。

よくある質問

なぜ -3^2 は 9 ではなく -9 になるのですか?
数学の慣例ではべき乗が単項マイナスより強く結合するため、2 乗が 3 に作用し、符号反転はその後に適用されます。9 が欲しい場合は (-3)^2 と書いてください。表計算ソフトは既定でこちらを想定します。
0.1 + 0.2 がちょうど 0.3 にならないのはなぜですか?
2 進浮動小数点では 0.1 を正確に表現できないため、加算後もごく小さな誤差が残ります。有効桁数 12 に丸めれば 0.3 と表示され、保持されている値は完全な精度を維持します。
三角関数を度に切り替えるには?
角度の単位を「度」にしてください。sin、cos、tan への入力が度として解釈され、asin、acos、atan は度を返します。pi/180 を手動で掛ける必要はありません。
どの定数が使えますか?
pi、e、tau(2 pi)、phi(黄金比)、そして無限大を表す inf です。名前は大文字小文字を区別しないため PI でも pi でも動作します。
大きな数の階乗も計算できますか?
倍精度が保持できる最大の階乗である 170! までです。それを超えると結果は無限大にオーバーフローします。階乗には非負の整数が必要です。
式は eval で実行されるのですか?
いいえ。専用のパーサーがトークン化して後置形式に変換し、小さなスタックマシンで評価します。入力した内容が JavaScript として実行されることは一切ありません。