たとえば、カスタム数式を評価するための最良の方法は何ですか
3+sqrt(5)+pow(3)+log(5)
PythonをC++に埋め込むことでそれができることを知っています;もっと良い方法はありますか?
ありがとう!
Boost.Spirit はC++パーサーライブラリです。
例:
'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;
}
C++の既製の標準ライブラリでこれを行う方法はありませんが、このような式を評価できる優れた解析アルゴリズムは数多くあります。
優れた解析アルゴリズムに関する参考資料が必要な場合は、 C++でのプログラミング抽象化 (無料でオンラインで入手可能!)の式解析に関する第14章を検討するか、 ダイクストラのシャント)を検討してください。 -ヤードアルゴリズム 。ここで説明する両方のアルゴリズムは実装が簡単で、式を比較的簡単に評価できます。
式を評価するためのよりハードコアなツールに興味がある場合は、 flex
および GNU bison
ツールを調べることを検討してください。この種の式のための強力なパーサーを構築します。 bison
のドキュメントには、算術式を解析および評価する方法も示されていると思います。そのため、作業はすでに完了している可能性があります。
お役に立てれば!
muParserX は、別のC++数式パーサーです。
C(そしてもちろんC++)からの算術式を評価するために、Luaのシンプルで使いやすいフロントエンドを作成しました。 http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#ae を参照してください。 OpenSouce C/C++数式パーサーライブラリ および 高速CまたはObjective-C数学パーサーとは も参照してください。
Lepton は、これを実行できる別のC++ライブラリです。式の解析と評価に加えて、さらに高度な機能もあります。たとえば、解析的な導関数を計算したり、式の基本的な代数式を単純化したりすることができます。ライブラリは非常に小さく、オープンソース(MITライセンス)です。
同様のタスクをライブラリで検索しているときに、 libmatheval を見つけました。適切なことのようです。残念ながら、GPLは私には受け入れられません。
Boost Spiritの最近のバージョン用に作成されたアプローチは次のとおりです。 http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-21-to-evaluate.html
最も簡単な方法は、外部ライブラリを使用することです。私が見つけた最も簡単なものは 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++に埋め込むことでそれが可能になることを私は知っています
それは可能ですが、単純な問題を解決するために大きな依存関係を引き込むことになります。
次のように文字列をフォーマットします。
#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
のアドレスを解決し、それを呼び出して結果を取得します。