数学パーサーを設計する最も賢い方法は何ですか? つまり、数学文字列 ("2 + 3 / 2 + (2 * 5)" など) を受け取り、計算値を返す関数ですか? 私はVB6で何年も前に書いていましたが、肥大化してしまい、あまり移植性がありませんでした(またはその点でスマートではありません...)。一般的なアイデア、疑似コードまたは実際のコードを歓迎します。
10 に答える
かなり良いアプローチには、2 つのステップが含まれます。最初のステップでは、式を中置記法から後置記法に変換します(たとえば、Dijkstra's shunting yard を使用)。それが完了したら、後置エバリュエーターを書くのはかなり簡単です。
数学パーサーの設計に関するブログ記事をいくつか書きました。一般的な紹介、文法に関する基本的な知識、Ruby で書かれたサンプル実装、およびテストスイートがあります。おそらく、これらの資料が役に立つでしょう。
いくつかのアプローチがあります。動的コードを生成して実行することで、多くのコードを書かなくても答えを得ることができます。.NET で実行時に生成されたコードを検索するだけで、多くの例が見つかります。
あるいは、実際のパーサーを作成し、式の評価に使用される小さな解析ツリーを生成することもできます。繰り返しますが、これは基本的な式については非常に単純です。そこに数学パーサーがあると思うので、codeplex をチェックしてください。または、例を含む BNF を調べてください。コンパイラの概念を紹介する Web サイトには、基本的な例としてこれが含まれます。
「常時オン」のアプリケーションを使用している場合は、数学文字列を Google に投稿して結果を解析するだけです。簡単な方法ですが、それが必要かどうかはわかりませんが、ある意味賢いと思います。
これは古いことは知っていますが、より大きなアプリの一部として電卓を開発しようとしてこれに遭遇し、受け入れられた回答を使用していくつかの問題に遭遇しました。リンクは、この問題を理解して解決するのに非常に役立ちました。私はJavaでAndroidアプリを書いていて、「文字列」という式の各項目について、ユーザーがキーパッドで入力すると、実際には文字列をArrayListに格納しました。中置から後置への変換では、ArrayList 内の各文字列を反復処理し、新しく配置された文字列の後置 ArrayList を評価しました。これは少数のオペランド/演算子にとっては素晴らしいことでしたが、特に式が非整数に評価され始めたとき、より長い計算は一貫してオフになりました。Infix から Postfix への変換用に提供されたリンク、スキャンされたアイテムがオペレーターであり、topStack アイテムの優先度が高い場合、スタックをポップすることを提案します。これはほぼ正しいことがわかりました。優先順位が高い場合、またはスキャンされた演算子と等しい場合に topStack アイテムをポップすると、最終的に計算が正しくなりました。これがこの問題に取り組んでいる人の助けになることを願っています。貴重なリンクを提供してくれた Justin Poliey (および fa?) に感謝します。
関連する質問優先順位のある方程式 (式) パーサー? これを始める方法についての良い情報もあります。
-アダム
開発者は常にクリーンなアプローチを望んでおり、解析ロジックをゼロから実装しようとしますが、通常はDijkstra Shunting-Yard Algorithm に行き着きます。結果はきれいに見えるコードですが、バグが含まれている可能性があります。私はそのような API JMEPを開発しましたが、安定したコードを作成するのに何年もかかりました。
これらすべての作業を行った後でも、JavaCC または ANTLR の使用に切り替えることを真剣に検討していることは、そのプロジェクト ページからでもわかります。
入力が文字列形式の中置式であると仮定すると、それを後置式に変換し、スタックのペア (演算子スタックとオペランド スタック) を使用して、そこからソリューションを実行できます。ウィキペディアのリンクで一般的なアルゴリズム情報を見つけることができます。
ANTLR は非常に優れた LL(*) パーサー ジェネレーターです。強くお勧めします。