web-dev-qa-db-ja.com

C ++で数式を評価するための最良の方法は何ですか?

たとえば、カスタム数式を評価するための最良の方法は何ですか

3+sqrt(5)+pow(3)+log(5)

PythonをC++に埋め込むことでそれができることを知っています;もっと良い方法はありますか?

ありがとう!

32
camino

Boost.Spirit はC++パーサーライブラリです。

例:

3
aaz

'pow'にパラメータが1つしかない理由はわかりませんが、 ExprTk ライブラリ次の単純なソリューションを導き出すことができます。

#include <cstdio>
#include <string>
#include "exprtk.hpp"

int main()
{
   typedef exprtk::expression<double> expression_t;
   typedef exprtk::parser<double>         parser_t;

   std::string expression_string = "3 + sqrt(5) + pow(3,2) + log(5)";

   expression_t expression;

   parser_t parser;

   if (parser.compile(expression_string,expression))
   {
     double result = expression.value();

     printf("Result: %19.15\n",result);
   }
   else
     printf("Error in expression\n.");

   return 0;
}
19
user5374653

C++の既製の標準ライブラリでこれを行う方法はありませんが、このような式を評価できる優れた解析アルゴリズムは数多くあります。

優れた解析アルゴリズムに関する参考資料が必要な場合は、 C++でのプログラミング抽象化 (無料でオンラインで入手可能!)の式解析に関する第14章を検討するか、 ダイクストラのシャント)を検討してください。 -ヤードアルゴリズム 。ここで説明する両方のアルゴリズムは実装が簡単で、式を比較的簡単に評価できます。

式を評価するためのよりハードコアなツールに興味がある場合は、 flex および GNU bison ツールを調べることを検討してください。この種の式のための強力なパーサーを構築します。 bisonのドキュメントには、算術式を解析および評価する方法も示されていると思います。そのため、作業はすでに完了している可能性があります。

お役に立てれば!

4
templatetypedef

muParserX は、別のC++数式パーサーです。

3
wildart

C(そしてもちろんC++)からの算術式を評価するために、Luaのシンプルで使いやすいフロントエンドを作成しました。 http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#ae を参照してください。 OpenSouce C/C++数式パーサーライブラリ および 高速CまたはObjective-C数学パーサーとは も参照してください。

2
lhf

Lepton は、これを実行できる別のC++ライブラリです。式の解析と評価に加えて、さらに高度な機能もあります。たとえば、解析的な導関数を計算したり、式の基本的な代数式を単純化したりすることができます。ライブラリは非常に小さく、オープンソース(MITライセンス)です。

2
peastman

私はC++とJavaで 単純な式パーサー を開発しました。現時点では、算術演算子+のみを処理します。 -、/ *ただし、より多くの機能に対応するために拡張できなかった理由はありません。

これらの簡単な例では、操車場アルゴリズムを使用して式を逆ポーランド記法に変換し、次に別の単純なスタックベースのアルゴリズムを使用して実際に式を評価します。

コードサンプルを見つけることができます ここ

1
AndyUK

同様のタスクをライブラリで検索しているときに、 libmatheval を見つけました。適切なことのようです。残念ながら、GPLは私には受け入れられません。

1
Yury

Boost Spiritの最近のバージョン用に作成されたアプローチは次のとおりです。 http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-21-to-evaluate.html

1
Rhys Ulerich

最も簡単な方法は、外部ライブラリを使用することです。私が見つけた最も簡単なものは TinyExpr です。これはCで書かれているので、C++から呼び出すのは非常に簡単です。また、1つのソースファイルと1つのヘッダーファイルのみです。統合は非常に簡単です。あなたはそれを得ることができます ここ

問題の例を解決するのは次のとおりです。

#include "tinyexpr.h"
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Result: %f\n", te_interp("3+sqrt(5)+pow(3,2)+log(5)", 0));
    return 0;
}

PythonをC++に埋め込むことでそれが可能になることを私は知っています

それは可能ですが、単純な問題を解決するために大きな依存関係を引き込むことになります。

0
yas777

次のように文字列をフォーマットします。

#include <boost/lexical_cast.hpp>
#include <string>
#include <math.h>

extern "C" {
std::string evaluate() { return boost::lexical_cast<std::string>(3+sqrt(5)+pow(3)+log(5)); }
}

C++コンパイラを呼び出して、上記のコードを共有ライブラリにコンパイルします。次に、その共有ライブラリをロードし、evaluateのアドレスを解決し、それを呼び出して結果を取得します。

0