【发布时间】:2011-02-25 10:01:35
【问题描述】:
例如,评估任何自定义数学表达式的最佳方法是什么
3+sqrt(5)+pow(3)+log(5)
我知道将 Python 嵌入到 C++ 中可以做到这一点;有没有更好的办法?
谢谢!
【问题讨论】:
标签: c++ math expression
例如,评估任何自定义数学表达式的最佳方法是什么
3+sqrt(5)+pow(3)+log(5)
我知道将 Python 嵌入到 C++ 中可以做到这一点;有没有更好的办法?
谢谢!
【问题讨论】:
标签: c++ math expression
不知道为什么'pow'只有一个参数,但是使用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++ 中使用现成的标准库是无法做到这一点的,尽管有许多很好的解析算法可以让您评估这样的表达式。
如果您想要一些关于良好解析算法的参考资料,请考虑查看 Programming Abstractions in C++ (免费且在线提供!)中的第 14 章表达式解析,或考虑查看 Dijkstra's shunting-yard algorithm。这里提到的两种算法都易于实现,并且可以让您相对轻松地评估表达式。
如果您对一些用于评估表达式的核心工具感兴趣,请考虑查看flex 和GNU bison 工具,它们可以为这些类型的表达式构建强大的解析器。我相信bison 文档甚至向您展示了如何解析和评估算术表达式,因此您可能已经为您完成了工作。
希望这会有所帮助!
【讨论】:
Boost.Spirit 是一个 C++ 解析器库。
例子:
【讨论】:
muParserX 是另一个 C++ 数学表达式解析器。
【讨论】:
我为 Lua 编写了一个简单易用的前端,用于评估 C(当然还有 C++)中的算术表达式。见http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#ae。另见OpenSouce C/C++ Math expression parser Library 和What is a fast C or Objective-C math parser?
【讨论】:
Lepton 是另一个可以做到这一点的 C++ 库。除了解析和评估表达式,它还具有一些更高级的能力。例如,它可以计算解析导数,并且可以对表达式进行一些基本的代数化简。该库很小,而且是开源的(MIT 许可)。
【讨论】:
最简单的方法是使用外部库。我找到的最简单的是TinyExpr。它是用 C 编写的,所以从 C++ 调用它应该很容易。而且,它只有一个源文件和一个头文件。非常容易集成。你可以得到它here。
解决您的示例问题只是:
#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++ 中可以做到这一点
你可以这样做,但你会引入一个巨大的依赖来解决一个简单的问题。
【讨论】:
这是为最新版本的 Boost Spirit 编写的方法: http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-21-to-evaluate.html
【讨论】:
我用 C++ 和 Java 开发了一个simple expression parser。目前他们只处理算术运算符+。 -, / * 但没有理由不能扩展它们以容纳更多功能。
这些简单的示例使用调车场算法将表达式转换为反向波兰表示法,然后使用另一个简单的基于堆栈的算法来实际评估表达式。
代码示例可以在here找到。
【讨论】:
在为类似任务搜索库时,我发现了libmatheval。似乎是一件正当的事情。不幸的是,GPL,这对我来说是不可接受的。
【讨论】:
像这样格式化一个字符串:
#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的地址,调用它,得到结果。
【讨论】: