【问题标题】:What is the best way to evaluate mathematical expressions in C++?在 C++ 中评估数学表达式的最佳方法是什么?
【发布时间】:2011-02-25 10:01:35
【问题描述】:

例如,评估任何自定义数学表达式的最佳方法是什么

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

我知道将 Python 嵌入到 C++ 中可以做到这一点;有没有更好的办法?

谢谢!

【问题讨论】:

标签: c++ math expression


【解决方案1】:

不知道为什么'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;
}

【讨论】:

    【解决方案2】:

    在 C++ 中使用现成的标准库是无法做到这一点的,尽管有许多很好的解析算法可以让您评估这样的表达式。

    如果您想要一些关于良好解析算法的参考资料,请考虑查看 Programming Abstractions in C++ (免费且在线提供!)中的第 14 章表达式解析,或考虑查看 Dijkstra's shunting-yard algorithm。这里提到的两种算法都易于实现,并且可以让您相对轻松地评估表达式。

    如果您对一些用于评估表达式的核心工具感兴趣,请考虑查看flexGNU bison 工具,它们可以为这些类型的表达式构建强大的解析器。我相信bison 文档甚至向您展示了如何解析和评估算术表达式,因此您可能已经为您完成了工作。

    希望这会有所帮助!

    【讨论】:

    • 不相关,但感谢有关 C++ 编程抽象的提示!
    【解决方案3】:

    Boost.Spirit 是一个 C++ 解析器库。

    例子:

    【讨论】:

    • 为 boost.spirit +1。但是,您的示例指向 1.8,这与以后的版本有很大不同(解析现在发生在 boost::spirit::qi 中)
    • @Tristram – 你是对的。我从发行版链接到当前版本,但其他两个链接仅适用于经典版本。
    【解决方案4】:

    muParserX 是另一个 C++ 数学表达式解析器。

    【讨论】:

      【解决方案5】:

      我为 Lua 编写了一个简单易用的前端,用于评估 C(当然还有 C++)中的算术表达式。见http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#ae。另见OpenSouce C/C++ Math expression parser LibraryWhat is a fast C or Objective-C math parser?

      【讨论】:

        【解决方案6】:

        Lepton 是另一个可以做到这一点的 C++ 库。除了解析和评估表达式,它还具有一些更高级的能力。例如,它可以计算解析导数,并且可以对表达式进行一些基本的代数化简。该库很小,而且是开源的(MIT 许可)。

        【讨论】:

          【解决方案7】:

          最简单的方法是使用外部库。我找到的最简单的是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++ 中可以做到这一点

          你可以这样做,但你会引入一个巨大的依赖来解决一个简单的问题。

          【讨论】:

            【解决方案8】:

            这是为最新版本的 Boost Spirit 编写的方法: http://agentzlerich.blogspot.com/2011/06/using-boost-spirit-21-to-evaluate.html

            【讨论】:

              【解决方案9】:

              我用 C++ 和 Java 开发了一个simple expression parser。目前他们只处理算术运算符+。 -, / * 但没有理由不能扩展它们以容纳更多功能。

              这些简单的示例使用调车场算法将表达式转换为反向波兰表示法,然后使用另一个简单的基于堆栈的算法来实际评估表达式。

              代码示例可以在here找到。

              【讨论】:

                【解决方案10】:

                在为类似任务搜索库时,我发现了libmatheval。似乎是一件正当的事情。不幸的是,GPL,这对我来说是不可接受的。

                【讨论】:

                  【解决方案11】:

                  像这样格式化一个字符串:

                  #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的地址,调用它,得到结果。

                  【讨论】:

                  • 为什么要将结果转换为字符串?
                  • 您需要将其转换为某个值,因为表达式产生的结果类型是未知的,字符串或双精度。
                  猜你喜欢
                  • 2010-11-29
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-12-05
                  • 1970-01-01
                  相关资源
                  最近更新 更多