Evaluate Math Expression

Evaluate Math Expression

eryar@163.com

摘要Abstract:本文简要介绍了数学表达式解析求值的几款开源软件,并结合程序代码说明了OpenCascade中表达式包的用法。也简要介绍了表达式解析求值在AVEVA Paragon模块中的应用。

关键字Key Words:Expression, Paragon, OpenCascade Expr package, muParser, MTParser

一、引言 Introduction

算术表达式中最常见的表示法形式有中缀、前缀和后缀表示法。中缀表示法(Infix notation)是书写表达式的常见方式,而前缀(prefix notation)、后缀表示法(postfix notation)主要用于计算机科学领域。算术表达式只包含操作数(operands)、二元操作符(binary operators)和一种括号(one kind of parentheses)。

Knuth将编写程序计算表达式的方法概括为三个步骤:

l 对中缀表达式进行语法分析;

l 中缀表达式到后缀表达式的转换;

l 对后缀表达式求值;

在《数据结构与算法》等相关的书籍中,还有如何将中缀表达式转换为后缀表达式的具体算法。

在AVEAV Plant(PDMS)的Paragon模块定义部件时,使用了参数化的表达式,从而实现了参数化的部件定义。其中参数化表达式的解析计算是其一个关键技术点。最近在写模型导出程序(Model Data Exchange Addin)时就遇到了这个问题,即参数化表达式的计算。好在AVEVA .Net给出了表达式计算类DbExpression,可以对PML的表达式进行解析计算,顺利解决了问题。

若想在自己的程序中实现数学表达式的解析求值,也有一些开源的工具可供选用。有些C++的数学表达式计算程序速度、效率还是很高的。在查看OpenCascade的文档时,发现其也有表达式求值的包,可用来对表达式进行计算。

发现OpenCascade已经有很多功能与AVEVA产品PDMS中的功能很类似,也难怪OpenCascade的前身Matra-Data Vision公司早期也有个集机械设计与工厂设计于一身的企业级并行工程解决方案Euclid集成系统。在1998年时Dassault Systèmes收购了EUCLID QUANTUM。

二、几款开源软件介绍 Introduce some tools

网上有很多开源的数学表达式解析求值的库,如:

l fparser

l muParser

l MTParse

在开源的二维CAD软件LibreCAD中就使用了muParser来对输入命令中的表达式进行解析。早期版本中使用了fparser。muParser小巧精干,提供LIB、DLL及源代码入方式。muParser最大的优点就是速度较快,更适合于实时性要求较高的环境,如Unix系统和单片机环境。源程序下载及文档说明可参考:

http://www.codeproject.com/cpp/FastMathParser.asp

MTParser优雅简洁,提供LIB、COM、源代码三种引入方式,是用典型C++风格编写的解析器,和muParser不同,它引入了多种设计模式,因而可扩展性的可维护性都很强。如作者所说,速度并不是TMParser最优先考虑的,也许文中所说的可扩展、可维护、易于使用、健壮性才是它的最大优势。源程序下载及设计文档可参考:

http://www.codeproject.com/Articles/7335/An-extensible-math-expression-parser-with-plug-ins

下面以一个具体实例来说明muParser的用法:(将muParser以源代码引入的方式加入到项目中),再编译如下代码:

 

 1 /*
 2 *    Copyright (c) 2013 eryar All Rights Reserved.
 3 *
 4 *        File    : Main.cpp
 5 *        Author  : eryar@163.com
 6 *        Date    : 2013-10-09
 7 *        Version : 1.0v
 8 *
 9 *    Description : Evaluate expression in muParser.
10 *                  
11 */
12 
13 #include <iostream>
14 
15 #include "muParser.h"
16 
17 int main()
18 {
19     mu::Parser parser;
20     parser.DefineNameChars("0123456789_"
21                        "abcdefghijklmnopqrstuvwxyz"
22                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
23                        "[]");
24 
25     double dParam1 = 2.0;
26     double dParam2 = 3.1415926 / 2.0;
27 
28     parser.DefineVar("PARA[1]", &dParam1);
29     parser.DefineVar("PARA[2]", &dParam2);
30 
31     parser.SetExpr("10 * (PARA[1] + sin(PARA[2]))");
32 
33     std::cout << parser.Eval() << std::endl;
34 
35 }

程序运行结果如下所示:

1 30 
2 Press any key to continue . . . 

如上程序所示,使用muParser可实现参数化表达式的计算,功能与AVEVA Plant(PDMS)中的Paragon模块中参数化表达式的计算方式已经很相近了。使用方法很简单。

三、Evaluate Expression in OpenCascade

在OpenCascade的TKAdvTools中有Expr包和ExprIntrp包,这两个包可用来对表达式进行解析和求值。但是在其文档《Foundation Classes User’s Guide》中并没有对TKAdvTools的工具进行说明。下面只给出一个简单实例来说明其应用,有兴趣的读者可以结合源程序对其具体实现进行研究。示例代码如下所示:

 

 1 /*
 2 *    Copyright (c) 2013 eryar All Rights Reserved.
 3 *
 4 *        File    : Main.cpp
 5 *        Author  : eryar@163.com
 6 *        Date    : 2013-10-09
 7 *        Version : 1.0v
 8 *
 9 *    Description : Evaluate expression in OpenCascade.
10 *                  
11 */
12 
13 #define WNT
14 #include <TCollection_AsciiString.hxx>
15 #include <Expr_GeneralExpression.hxx>
16 #include <ExprIntrp_GenExp.hxx>
17 
18 #pragma comment(lib, "TKernel.lib")
19 #pragma comment(lib, "TKAdvTools.lib")
20 
21 int main(void)
22 {
23     TCollection_AsciiString strExpr("sin(3.1415926 / 6) * 2");
24     Handle_ExprIntrp_GenExp exprIntrp = ExprIntrp_GenExp::Create();
25     Handle_Expr_GeneralExpression genExpr = NULL;
26 
27     exprIntrp->Process(strExpr);
28 
29     genExpr = exprIntrp->Expression();
30 
31     std::cout << genExpr->EvaluateNumeric() << std::endl;
32 
33     return 0;
34 }

程序运行结果如下所示:

1 1 
2 Press any key to continue . . . 

OpenCascade的表达式求值功能也很强大,这里只以一个简单示例来抛砖引玉啦。感觉OpenCascade的表达式包也可以像muParser, MTParser一样作为一个独立的工具来使用。

四、结论 Conclusion

因为AVEVA Plant(PDMS)的Paragon模块中的参数化部件定义方式,注意到了参数表达式的解析与求值。由于ModelDataExchangeAddin程序的需要,才去找寻开源的表达式解析与求值的库,谁知最后还是使用了AVEVA .Net中现成的DbExpression类,简化了程序的开发。

OpenCascade中竟然也有表达式解析与求值的工具,作为早期机械设计与工厂设计软件系统,可能都考虑过参数化这种方式。深入挖掘其源代码,对类似PDMS的工厂设计系统实现原理的理解有很大帮助。

五、参考资料 Bibliography

1. http://www.ibm.com/developerworks/cn/java/j-w3eva/

2. http://en.wikipedia.org/wiki/Euclid_(computer_program)

 

PDF Version: Evaluate Math Expression

时间: 2024-10-03 12:11:31

Evaluate Math Expression的相关文章

OpenCASCADE Expression Interpreter by Flex &amp; Bison

OpenCASCADE Expression Interpreter by Flex & Bison eryar@163.com Abstract. OpenCASCADE provide data structure of any expression, relation or function used in mathematics. Flex and Bison are tools for building programs that handle structured input. Th

OpenCASCADE Outline

OpenCASCADE Outline eryar@163.com      有网友反映blog中关于OpenCASCADE的文章比较杂乱,不太好找,最好能提供一个大纲,这样方便查找.于是决定将这些学习时写的文章整理下,方便对OpenCASCADE的学习理解.其实在http://www.cnblogs.com/opencascade中,已经将文章按目录重新发表了一遍.可以按OpenCASCADE的模块的顺序来学习,也可以挑选自己感兴趣的部分来学习.      由于本人水平所限,文中的错误不妥之处

[LeetCode] Parse Lisp Expression 解析Lisp表达式

You are given a string expression representing a Lisp-like expression to return the integer value of. The syntax for these expressions is given as follows.  An expression is either an integer, a let-expression, an add-expression, a mult-expression, o

一种基于 JEP 和可配置公式实现用户自定义字段的解决方案

背景 随着 IT 技术的普及和发展,用户的信息化水平越来越高,软件产品除了满足用户的基本需求 之外,还必须越来越照顾到用户的个性化需求,为用户提供深层次的个性化服务.以一个包含报表展示功能的 产品为例,默认呈现给所有用户完全相同的报表,即同一个报表的字段内容和标签对所有用户完全相同.而在 实际中,我们常常会遇到不同的用户由于其业务需求的不同,对于同一张报表,除基本数据字段之外,还要求 额外增加符合该用户特定业务含义的字段,我们称之为用户自定义字段(Custom Metric).这类需求在财务 报

基于JEP并结合可配置公式实现用户自定义字段的解决方案

随着 IT 技术的普及和发展,用户的信息化水平越来越高,软件产品除了满足用户的基本需求之外,还必须越来越照顾到用户的个性化需求,为用户提供深层次的http://www.aliyun.com/zixun/aggregation/17516.html">个性化服务.以一个包含报表展示功能的产品为例,默认呈现给所有用户完全相同的报表,即同一个报表的字段内容和标签对所有用户完全相同.而在实际中,我们常常会遇到不同的用户由于其业务需求的不同,对于同一张报表,除基本数据字段之外,还要求额外增加符合该用

像职业选手样编码:地道Python

Code Like a Pythonista: Idiomatic Python David Goodger goodger@python.org http://python.net/~goodger In this interactive tutorial, we'll cover many essential Python idioms and techniques in depth, adding immediately useful tools to your belt. There a

用Python编写一个简单的Lisp解释器的教程_python

本文有两个目的: 一是讲述实现计算机语言解释器的通用方法,另外一点,着重展示如何使用Python来实现Lisp方言Scheme的一个子集.我将我的解释器称之为Lispy (lis.py).几年前,我介绍过如何使用Java编写一个Scheme解释器,同时我还使用Common Lisp语言编写过一个版本.这一次,我的目的是尽可能简单明了地演示一下Alan Kay所说的"软件的麦克斯韦方程组" (Maxwell's Equations of Software). Lispy支持的Scheme

表达式求值、表达式转二叉树

1.后序表达式求值: 后续表达式(逆波兰式)的特点:没有括号. 求值方法: 从前向后扫, 遇到操作数压栈: 遇到操作符,从栈中取出2个操作数运算,结果压栈. 最终栈中所剩的数为结果. 2.中序表达式求值 我们先来定义运算符的优先级: ( +,- *,/,% 从上到下依次升高 准备2个栈,一个专门存放运算符,另一个专门存放操作数. 1.遇到),那么退栈计算到(为止.结果压栈. 2.遇到运算数.那么压栈. 3.如果当前运算符优先级低于栈顶运算符.那么计算栈顶运算符并将结果压栈. 4.否则压栈. 计算

UVa 11234 Expressions:二叉树重建&amp;amp;由叶往根的层次遍历

11234 - Expressions Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2175 Arithmetic expressions are usually written with the operators in between the two operands (which