用户:  密码: 记住我     找回密码 
| 文章 >> 编程通用 >> 算法

一个可扩展的数学表达式解析器插件

日期 | 作者 | 浏览86 | 评分100 | 标签算法 评论
{A}{S0}简介几乎所有的应用程序使用数学表达式
。事实上,他们是编程语言的基础。当您键入一个程序,你实际上是写数学公式吨。程序是静态的性质,也就是说,它不能被改变,而执行。例如,在C语言编写的程序必须重新编译每次更改一个单一的代码行。因此,可以想象,一个数学公式进行修改,以适应用户环境的变化。你想重新编译所有的代码只是一个小公式变化的想法?这就是一个数学表达式计算器的实用性,因为它允许运行时的公式评估和修改,而不需要改​​变,甚至一行代码。诀窍是处理数据,而不是程序指令的数学公式。评估作为字符串的公式,他们上飞编译,和计算结果,可用于您的应用程序透明。
数学软件是一个成熟的领域,有很多优秀的库以最低的收费。因此,提供增强的数学功能和算法,是不是这个解析器的主要任务。相反,重点是允许重用现有代码,在运行时间公式评估中。为此,解析器设计定义了现有的功能可以优雅被集成的框架。插件是延长解析器,如果你开发了一个,我请你给我你的组件的特权方式。
有两个版本的分析器:一个原生的C库,和一个COM组件。 C库是高度可扩展和快速的,但它的使用是有限的C语言。对口,COM组件很容易集成在一个项目中,和许多编程语言都可以使用它。 COM的插件可以用于扩展C库和COM组件。
本文的结构如下: {A18}{A19}{A20}{A21}{A22}{A23}{A24}{A25}{A26}{A27}{A28}{A29}{A30}{A31}{A32}{A33}{A34}{A35}{A36}{A37}{A38}{A39} {A41}{A42}{A43}{A44}{A45}{A46}
在这里的主要特点是:用户定义的函数和操作符
C函数和操作符类可以被定义为扩展解析器语言。通常情况下,这些类将被打包成一个插件,允许运行时间的延长。用户定义的变量和常量
变量是一个特殊的符号,评估值取代,但不像一个常数,其值是可以改变的。可以用来做参数的公式,如??T 10??其中,t是时间变量。在运行时可以定义一个变量的数量不受限制。
常量是一个特殊的符号,评估值取代。使用常量而不是值,有助于更清晰的数学公式,特别是众所周知的值。分析器还可以做的优化,因为它知道这些值是常数。常量的例子是PI(3.14159?和E(2.71??可以在运行时定义的常量的数量不受限制。用户定义的宏
宏功能有助于简化经常使用的词句的写作。例如,如果你经常使用欧几里德距离定义为SQRT(X ^ 2 Y ^ 2),然后它可能是一个好主意,以定义一个名为"EUC(X,Y)?宏??一个宏可以使用任何定义的运算符,函数,常量和宏。可以在运行时定义的宏的数量不受限制。批量评估
要达到非常高的性能,你可以计算表达式多次,使用一个不同的值设置每次在一个函数调用。这样,您就节省昂贵的函数调用时,尤其是当使用COM库的版本。其结果是,在C#中使用COM库的版本开发的一个客户端执行一个非托管的C应用程序几乎达到70%!插件扩展
插件增加功能,运营商和常量允许运行时分析器的语言扩展。加载多个插件,可根据用户需求,从而使您的应用程序运行时定制,使基于组件的发布管理政策(用户只需支付他们所使用的功能)。一个插件架构的另一个好处是,可以很容易地与您的应用程序集成第三方组件。有趣的是,知道插件本地C函数和运算符的快速。国际因素
今天的国际软件市场需求的本地化的应用程序。此组件已被认为它从一开始,和本地化的任务是简化。本地化的错误消息每种语言的XML文件存储在
参数的错误消息。所有的错误来补充领域,允许生产出非常丰富的信息。有没有内部消息:所有邮件可以本地化。 本地化文档
文件可以提供与函数,运算符,常量,变量,以帮助用户找出如何使用它们。文档文本存储在一个XML文件。可配置的语法
十进制数和函数的参数分隔符字符,可以在运行时修改根据用户的喜好自定义的语法。Unicode的准备
的所有字符串都是以Unicode处理。这包括变量,常量,运算符,和函数名。然而,使用一个简单的编译选项,您仍然可以使ANSI字符串。许多预定义的运算符和函数
超过16家运营商和30个函数。布尔值,三角函数,和数值逼近功能都包括在内。这仅仅是开始,因为插件可以载入延长分析器语言。
操作符:
-

/
^

放大器;
|

GT,GT =
LT,LT;!=
=
==此外
减法和负号


司功率

逻辑
逻辑"或"
逻辑NOT
大于或等于
小于或等于
不等于
平等
一般功能:ABS

ACOS ASIN
ATAN
AVG(X,Y,Z,??斌

CEIL
COS
吸烟与健康委员会其实地板

十六进制

的isNaN
登录
LOG10
最大(X,Y,Z,??
分钟(X,Y,Z, ?RAND()
一轮兰特(最小值,最大值)


SINH SQRT


SUM(X,Y,Z,??谭
TANH
数值逼近函数(数值逼近插件):衍生物(expr中,VAR,点)



梯形(expr的,VAR,A,B,[步= 0.1])



解决( expr中,VAR,结果,VO = 0],[TOL = 0.01],[maxIter = 100])计算一个变量的数值逼近衍生的表达,在指定的点

A和B使用梯形法则

查找变量的值之间的积分计算一个数值逼近产生预期的效果,使用牛顿的数值逼近方法
日期/时间功能(日期插件):日期
DATEVALUE

小时
分钟

nowdate nowtime
第二个时间

周日
一年用户定义的函数编译器
为了让要使用特殊的语法,函数可以编译他们的论点,他们想要的方式。大多数功能都好了,只用数字,但一些复杂的功能,需要更多的灵活性。例如,解决功能作为其第一个参数的数学表达式,甚至可以提供可选参数。的错误信息
错误报告通过异常结构,使生产出非常的错误信息的详细领域。异常结构字段包含信息"是什么??"每个错误??的。速度非常快快速算法
使用,以保证优良的性能。一些技术使用表达式编译常量表达式折叠,和二进制搜索。
一个大的功能列表,并没有必要让一个很好的解析器。质量也是非常重要的。因此,素质一流的数学解析器有吗?如果你想使用它在一个实时的应用程序,然后性能是必须的。因为实时应用往往不使用Windows,解析器必须移植到其他平台。如果这是您的情况下,不失去这个解析器你的时间,因为它不是在西部的"最快的解析器??,也不是它的便携式。
然而,这个解析器有一些非常有趣的素质!一点点的性能已经成交的可扩展性,代码的可维护性,易用性和鲁棒性。这些特质,每个人都有一个对性能产生负面影响,但它不负有心人其他方式:可扩展性使您可以轻松地添加运算符和函数,使用清洁,面向对象的代码,而无需修改现有的代码。这将避免引入微妙的错误,浪费你的时间调试破解析器。另一个好处是,你不需要了解内部的解析器逻辑添加运算符和函数。可维护性开源库的情况下肯定是不可取的!没有晦涩的代码性能的缘故。暗码的特点,没有人愿意修改最简单的变化,但。可维护性定义便于理解,易于修改,易于测试,并易于预测修改副作用。易于使用,保证它不会在颈部疼痛与您的项目相结合的解析器。这将允许您专注于您的应用程序,而不是浪费时间,了解一个复杂的解析器接口。另一个方面是国际化:它可以是非常耗时的一个还没有被这个思想库从一开始国际化。鲁棒性是指您的应用程序不会崩溃,因为缺少一些验证代码。如你所知,用户善于发现这些小的孔??这也意味着,解析器将给予正确的结果,并做必要的验证,以确保结果的有效性。例如,分析器,不得接受可能有副作用的语法,如:??2.2.3 3.2.3??这是两个非常不同的事情:工作,按预期方式工作。当然,解析器非常快!但正如我所说,这是重中之重,因此,有时选择是阻碍性能(不是没有任何反省???).
不要误会我的意思:这个解析器是不是在所有上述素质方面的完美。但这些特质是我照顾,将继续引导解析器对。{A47}
免费用于非商业目的。如果你想使用这个分析器在一个商业化的产品,请使用以下信息与我联系:您的编程语言对你有用的功能(见{A48})解析器如何帮助您的简短说明
事实上,即使你在个人项目中使用这个库,我真的很高兴能听到你的一些字!因此随时分享您的经验。{A49}
本节介绍的整体设计和权衡。{A50}
下面的设计图案已经使用的门面,原型,抽象工厂和国家。外墙说明:分析器是由多个类和接口,协作,以提供数学评估服务。这样的分工是为了获得一个干净的设计要求。然而,分析器用户不关心的内部设计,并因此需要以用户为中心的界面。门面提供了这种观点。后果:提高通过隐藏实现细节,使用分析器缓解。减少可见类的数量减少客户端和库之间的耦合。合作者:客户端
客户端库的用户。例如,您的应用程序代码。唯一的类,你需要了解的是MTParser。MTParser
这是外观类。它提供了一个注册和编译器的服务,都在一个界面。此外,它定义辅助方法,以简化常见任务的执行。MTParserRegistrar和MTParserCompiler
分析器是由多个对象(例如,一个编译器和一个注册)为了不把整个负担,在相同的对象,这将是过于庞大。 MTParserRegistrar和MTParserCompiler对象每个处理的数学评价任务的一部分。原型说明: 可在运行时定义自定义的函数和运算符,所以解析器不知道这些对象。在这种情况下,解析器如何可以复制这些对象时,它需要克隆自己呢?原型是支持克隆的对象。因此,所有的功能和操作的对象是可以克隆自己的原型。产卵的方法是用来问一个对象重复自己。后果:允许运行时项目的定义和创作(功能,运营商??没有项目和分析器之间的耦合,虽然解析器需要创建项目实例。从一个工厂的创作模式,工厂需要了解具体的类,这是非常不同。该项目的类处理创建任务的复杂性。事实上,一个项目需要知道如何复制自己。这是一个小的开销,当创建一个新的项目类别,但避免修改解析器代码。合作者:{S2}MTParser
当初始化一个分析器,从现有的解析器对象(使用=操作符C或COM版本的复制方法)所有定义的项目需要重复。然后,解析器要求每个项目建立一个新的项目实例。新的实例是完全独立的,但原项目相同的状态。MTFunctionI和MTOperatorI
这些项目的接口。产卵的方法是使用要求复制的对象。 SinFct和任何其他具体项目类
这些类知道如何克隆自己。创造可能只有一个类的实例,或许多操作,包括重复的对象国。好事是,这种逻辑是封装在具体项目类,并没有其他的也知道。抽象工厂说明:抽象工厂模式是定义一个工厂接口,并用它来获得对象。工厂方法模式的区别是,直到运行时是不知道具体工厂类。这可以调换插头的上下文。我们希望能够从一个默默无闻的DLL加载未知的项目(即函数,运算符和常量)。抽象工厂接口对应的COM插件在IDL中,它返回新项目对象的方法。实施该项目的类可以使用原生C类。一旦分析器对每个项目的对象,插件是没有更多的原型模式是必要的,因为用于复制现有的项目。这大大简化了插件在制定。后果:当一个插件,因为这是一个原生的C类(即,没有COM调用,访问对象是直接调用)定义了一个项目的零的性能损失。 COM调用只在初始化步骤,当定义插件项。因为他们是C类,项目可以像使用自定义编译C分析器服务。有没有特殊的互操作性的考虑,如果C和COM对象的混合使用,会发生。插件是简单的创建,因为他们的COM接口是最小的。只有少数几个工厂相关的方法是必要的。没有COM接口函数和运算符是必需的。插件在维护缓和以来,工厂的接口相当稳定。然而,项目接口经常发生变化,但很容易改变一个C类??接口比COM接口。合作者:{S3} IMTPlugin
这是抽象工厂接口。它的方法来创建新的功能和操作对象。一旦所有项目的创建,插件可以卸载。 插件实现
这是具体的插件类。它知道所有插件函数和操作符类,从而可以创建新的对象,并返回给解析器。MTParser
解析器使用功能和操作员通过MTFunctionI和MTOperatorI接口的对象。它与通信插件使用的IMTPlugin界面。当加载一个插件,解析器要求工厂为每个项目的一个对象。在此之后,解析器使用直接的项目对象。MTFunctionI和MTOperatorI
C接口定义的职能和经营者提供的服务。func1的和OP1
这些都是在插件中定义的功能和运营商。项目代码是由操作系统动态加载在内存中,使用的DLL机制。解析器对象一旦创建,只需要通过插件接口获得的内存的指针。国家说明:编译器解释各不相同,其当前状态而定的字符。例如,解析转换功能参数的同时,运营商的字符不意味着什么。状态模式大大简化,避免重复和处理多个复杂的特殊情况下的编译器的代码吗??代码>如果??报表。一个解决办法是把涉及到一个单独的类,每个国家的代码。这样一来,编译器可分为一般解析器和多个国家。后果:可以添加新的国家,而不会影响编译器的代码。这意味着,新的编译器功能,可以很容易地添加。实施一个新特点是通过创建一个新的国家一类,而不是将代码添加到一个已经巨大的解析方法。解析和编译任务可以分开的。这使得一般解析器识别标记,解释工作,并委派到当前编译器状态。没有什么大的单片编译器类。相反,有几个小班授课,和一般的编译器类,它提供共同服务的状态类。合作者:{S4}的MTParserCompiler
这个表达式的编译器。它提供了解析(标记生成器)和一般堆栈管理服务。当一个标记(例如,运营商的名称),它调用当前编译器状态对象。MTCompilerState
这是一个接口,这是所有国家都必须符合。每个方法对应一个确定的令牌事件。例如,当检测到一个运营商的名称是,onOp方法被调用。它是由国家来决定做什么与每个事件。它还决定何时改变现状。具体状态
目前有三种状态。下列过渡的图显示了什么触发每个国家。{五}{A51}
第一个图显示数学表达式组成。 MTParser类是外观,隐藏了两个更复杂的类,是一个处长和一个编译器。司法常务官的职责是:注册有效的表达项目。确保在冲突中没有项目。确保整个quot; languagequot;是一致的。访问登记事项。
编译器的职责是:中缀符号的表达,它转换为一个堆栈的顺序进行评估的项目。验证表达式的语法。
三个对象解析器分离实际上降低了每个对象的复杂性,而且会缓解特殊的注册商或编译器的处理。例如,我们自然可以想像的编译器会做的某些类型的优化,用户可以选择使用或不。
有可能已经评估另一个对象。这个对象将负责评估表达式的结果,使用的编译器做的堆栈。问题是,这将引入一个呼叫间接从外观评估。可悲的是,这种间接的评估方法,因为被称为重复,因此,每个间接时间乘以千倍的成本太高。{中六}
下面的类图显示了运算符,函数和变量如何被抽象。在底部,我们看到的具体操作和功​​能类。可以添加新的运营商和职能简单地实施MTOperatorI和MTFunctionI接口。运算符和函数之间的区别是,一个函数可以有任意数量的参数和运营商有一个变量的优先级(函数必须具有在比运营商更大的优先顺序解析算法正常工作)。
另一种设计可以合并这两个接口,但是这可能会导致不好的功能和运营商实现,因为运营商是有限的两个参数的优先级是固定的功能。因此,在这种情况下,我更喜欢通过添加一个接口,增加设计的复杂性,以避免编码错误。 MTExprItemEvaluatorI接口定义为一个表达式的评估所需的通用方法。这是关键,以防变化的数学表达式计算器,并保持代码清洁。{七}
下一个类图显示数学解析器的依赖关系(MTParser类)。我们看到,它必须知道表达的项目是否是一个函数,操作员,或一个变量,以专门处理每个类型。这意味着,如果添加一个新的项目类型,解析器将需要进行修改。当然是有改进的余地,但这种类型的更改可能没有足够频繁支付的解析速度可能发生的损失。
最后,在未来的类图显示了在表达式求值的阶级关系。有没有具体的项目接口(即MTOperatorI,MTFunctionI??,这意味着评价逻辑不会需要改变,除非改变非常最通用的接口(即,MTExprItemEvaluatorI)。{S9}{A52}{A53}
基本上,数学分析器允许你使用你的数学表达式的定义中的下列项目:数字值,常量,变量,运算符,和功能。基本法。数学表达式,然后进行预处理,是建立一个堆栈(请注意,这是一个堆栈,而不是一棵树)加快评估。这样,大的处理是在解析的时候只有一次。这是一个非常普遍和有效的算法来分析数学表达式的,所以我不会放弃这里有很多细节。
在这里的主要思路。首先,你有两个堆栈:一个临时栈将用于商店经营者(即运营商栈),另一个栈将包含前处理表达,稍后将被用来做评估(其命名为第二栈)。解析是由左到右。所以,如果你得到一个号码,你把它立即在第二个堆栈。所有后续的数字你做同样的事情。现在,如果你得到一个运营商(名称它curOp),你会做以下事情:
If precedence(curOp) > precedence(lastOp) then

  push curOp on the operator stack

Else

  While precedence(curOp) <= precedence(lastOp)  

    pop lastOp

    push lastOp on the second stack   

  push curOp on the operator stack

EndIf

最后,弹出所有剩余的运营商,推动他们的第二个堆栈。
这一切​​的目标是把堆栈顺序的底部高优先级运营商,他们将首先评估。优先级在这里指的数学运算符优先级。 , - 有相同的优先级,并*有更大的优先级高于另外,lastOp是在操作堆栈(换句话说,它的最后一个运算入栈)的顶层元素??。在评价时,你弹出项目逐一和计算结果。实际执行递归(见更多细节代码)。这是所有!当然,有些代码是需要处理的功能和括号,但一旦你捕获的基本思路,这是非常简单的。
在更多的技术术语,这种算法是俗称的调车场算法或简单运算符优先级解析算法。其目的是为了改造表达式串缀表示法使用逆波兰形式。中缀表示法是我们人类,通常使用写数学表达式(例如,X 2 * 2),逆波兰表达式是一台电脑可以更好地理解,因为没有必要担心运算符优先级和括号。后者的一个例子是在下面的部分。{A54}
给出的表达式2 ^ 3 4 * 5,申请解析算法,给出了以下的协议栈(1列):
{S10}
(突出显示弹出项目)
评价算法的持久性有机污染物的第一项和评估。在这种情况下,经营者是回升(#1)。加法运算需要两个参数,所以持久性有机污染物是*操作符(#2)第一个参数。同样,乘法运算符需要两个参数,并弹出第一个参数为5,第二个参数为4(#3)。 *运营商现在可以进行评估,并为运营商,成为第一个参数,返回20。接下来,持久性有机污染物的加法运算符^(#4)第二个参数。 ^运算,然后弹出两个参数,第3和2(#5),并返回8。最后,该运算符返回28,也就是8和20的总和。
伪代码: {C}
再次,这是基本的算法。事实上,它仅在分析步骤,和一个更快,迭代算法是在评估步骤。{A55}
本节说明如何实现与MTParser C库和COM组件最常见的任务。将使用C代码来说明如何使用C库,同时,为了多样性,VB6和C#代码将使用COM组件。
开始之前评估的数学公式,你必须与您的应用程序集成的解析器。[C]{A57}
你必须选择!如果你想按照国际化的指引,你应该使用Unicode。 ??EM> UnicodeANSIDefs.h??文件,表明您的选择。这个文件是根据您选择的字符串格式来定义正确的字符串操作函数。例如,在库中的代码,而不是使用std:字符串直接MTSTRING是使用。然后,如果使用Unicode版本,MTSTRING将被定义象std::wstring的。这是,允许库使用Unicode或ANSI字符串(而非两组)的伎俩。{A58}_MTPARSER_USE_PLUGIN:如果定义,插件功能将被编译。_MTPARSER_USE_LOCALIZATION:如果定义,定位功能将被编译。
这些标志的定义,默认情况下,在MTParserPublic.h文件中。{A59}
如果你没有的。lib文件,那么你将有自己编译库。您将能够与Visual Studio 6。NET 2003和。NET 2005的编译库。
注意:一定要具有相同运行时库的版本,在您的项目(例如,多线程DLL)编译。
下面的列表给出了每个项目的简短描述:MTParserLib:核心C解析器库。COM库:COM解析器库版本。允许多国语言的使用分析器的功能。 COM库的版本是只有围绕核心库的包装。 MTParserInfoFile:COM对象来读取XML文件信息本地化的需要。它使用。NET XML服务,是因为核心库外。NET服务是没有用VC6。插件/ MTParserPlugin:插件IDL接口生成TLB文件。插件/ MTDatePlugin:插件的日期和时间。插件/ MTNumAlgoPlugin:数值算法插件。代码示例/ C库/ C客户端:主要演示应用程序使用C解析器库的版本。代码示例/ COM库/ C客户端的C演示应用程序使用的COM解析器库版本。代码示例/ COM库/ C#的客户端:C#的演示应用程序使用的COM解析器库的版本。代码示例/ COM库/ VB客户端:VB6的演示应用程序使用的COM解析器库版本。
如果您只使用基本功能,你只需要编译的MTParserLib项目。Visual Studio的6
转到项目设置| C / C |代码生成,然后"使用运行时库??如果你编译库比在您的项目具有不同的运行时库,然后你会得到链接错误,说明有多个符号定义。
使用Visual Studio 6,您将能够编译下列项目:MTParserLib / MTParserLib.dsw代码示例/ C库/ C客户端/ MathExpr.dswNET 2003中,2005的Visual Studio。
转到项目属性页,然后到C / C |代码生成,然后"运行时库??通常情况下,您将使用多线程调试DLL,在调试模式下和多线程在释放DLL。
使用Visual Studio。NET中,您将能够编译VB6的例子以外的所有项目。{A60}
只有头文件,你需要包括MTParser.h和MTParserLocalizer.h,如果您使用的本地化功能。数学分析器类是MTParser:
#include "../MTParserLib/MTParser.h"

#include "../MTParserLib/MTParserLocalizer.h"

注:我认为图书馆是位于您的项目目录旁边。例如,如果你的项目是在C:\项目\ MyProject的\,然后数学解析器库在C:\项目\ MTParserLib \。 {A61}
有四个库的版本,每个调试/发行和ANSI / Unicode的组合之一。你会发现在lib目录下MTParserLib的lib文件。您可以添加到您的项目链接设置适当的库,或者使用下面的预编译命令:
#ifdef _DEBUG

  #ifdef _UNICODE

    #pragma comment(lib, "../MTParserLib/lib/MTParserUd.lib")

  #else

    #pragma comment(lib, "../MTParserLib/lib/MTParserd.lib")

  #endif

#else

  #ifdef _UNICODE

    #pragma comment(lib, "../MTParserLib/lib/MTParserU.lib")

  #else

    #pragma comment(lib, "../MTParserLib/lib/MTParser.lib")

  #endif

#endif

上面的代码将自动链接库,根据项目设置适当的版本。
我恳请您使用的发行版本,当标杆您的项目,因为它是真正更快。 [VB6]
你所要做的唯一的是添加在您的项目引用MTParser组成部分。要在Visual Basic 6.0,转到项目|引用|浏览,然后浏览该MTParserCOM.dll文件。最常见的问题是忘记在您的系统中注册的COM文件。要手工做,使用Regsvr32.exe应用程序位于Windows \ System32目录。运行"REGSVR32 MTParserCOM.dll??[C#]
你所要做的唯一的是添加在您的项目引用MTParser组成部分。要在Visual Studio.net 2003年,转到项目|添加参考|浏览,然后浏览该MTParserCOM.dll文件。正如在上面VB6的部分所说,确保注册COM文件。要使用的解析器命名空间中添加以下行:
using MTPARSERCOMLib;
{A62}
,您可以创建一个新的对象和配置从头开始,或者你可以复制现有对象的配置。{A63}
这是创建一个新的解析器对象的基本途径。默认的配置,包括默认的运营商和职能,并使用点(。)作为小数点字符和昏迷(,)作为函数的参数分隔符字符。[C]
调用空的构造:
MTParser parser;  // default configuration
[VB6]
像往常一样创建一个新的对象:
Dim parser As New MTParser
[C#]
像往常一样创建一个新的对象:
MTParser parser = new MTParser();
{A64}
当你要使用多个解析器对象,这是更方便的配置只有一个对象,然后创建它的副本,比配置。所有对象的状态是重复的,其中包括:目前的数学公式,变量,常量,自定义功能,运营商定制,和语法。这种重复是必要的保证,新对象将继续正常工作,虽然原来的对象被销毁。[C]
有两种方法来配置一个新的对象,使用另一个对象的配置。第一种方式是使用拷贝构造函数,第二个是调用赋值运算符:
MTParser parserTemplate;

// Configure the template object?/span>

parserTemplate.enableAutoVarDefinition(true);



// Using the copy-constructor to configure a new object 

MTParser parser2(parserTemplate);



// Using the assignment operator to configure an object

MTParser parser3;

parser3 = parser2;
[VB6]
Dim parserTemplate As New MTParser

Dim parser As New MTParser

'Configure the template object?/span>

parserTemplate.autoVarDefinitionEnabled = True



' Using the copy method to re-configure an object

parser.Copy parserTemplate
[C#]
MTParser parserTemplate = new MTParser();

MTParser parser = new MTParser();

// Configure the exprTemplate object?/span>

parserTemplate.autoVarDefinitionEnabled = 1;



// Using the copy method to re-configure an object

parser.Copy(exprTemplate);
{A65}
这是这个库的主要目的!如果你要计算一个简单的表达式一样的结果吗?? 2??或任何任意复杂度和长度,像"PI *(XY罪(Z)/ 2 ^ 3-40.9988 * 2,AVG(Y,X * 10,3,5,的表达))???那么这部分显示了它是如何工作的。{A66}
这是最简单和更直接的方式计算表达式。[C]
MTParser parser;

MTDOUBLE result = parser.evaluate(_T("2+10*2"));
[VB6]
Dim parser As New MTParser

Result = parser.Evaluate("2+10*2")
MTParser parser = new MTParser();

double result = parser.evaluate("2+10*2");
{A67}
int nbEvals = 1000;        

MTDouble x = new MTDouble();

x.create("x", 0.0);



MTParser parser = new MTParser();

parser.defineVar(x as IMTVariable);

parser.compile("x+2*sin(x)");



for( int t=0; t < 1000; t++ )

{

  x.value = t; // new variable value

  double result = parser.evaluateCompiled(); 

}
MTDoubleVector x = new MTDoubleVector();

x.create("x");



MTParser parser = new MTParser();

parser.defineVar(x as IMTVariable);



// Allocate memory for variable values and results

double[] xval = new double[nbEvals];

double[] results = new double[nbEvals];        



// Add your code to fill the value vector?/span>



// Assign variable values

x.setValueVector(xval);



// Compile the expression only once

parser.compile("x+2*sin(x)");

// Evaluate the expression for all

// variable value in one function call

parser.evaluateCompiledBatch(nbEvals, results);
MTDOUBLE myVar;

MTParser parser;

parser.defineVar(_T("x"), &myVar);
myVar = 10;
{A70} {A71}{A72}
MTParser parser;

parser.defineConst(_T("pi"), 3.14159265359);
MTParser parser = new MTParser();

parser.defineConst("pi", 3.14159265359);
{A73}
// Random with zero argument

class RandFct : public MTFunctionI

{



  virtual MTSTRING getSymbol(){return _T("rand"); }



  virtual MTSTRING getHelpString(){ return _T("rand()"); }

  virtual MTSTRING getDescription()

      { return _T("Random value between 0 and 1"); }

  virtual int getNbArgs(){ return 0; }



  virtual bool isConstant(){ return false; }



  virtual MTDOUBLE evaluate(unsigned int nbArgs, const MTDOUBLE *pArg)

  {

    return rand()/(double)RAND_MAX; 

  }



  virtual MTFunctionI* spawn(){ return new RandFct(); }

};


// Random with two arguments

class RandMinMaxFct : public MTFunctionI

{



  virtual MTSTRING getSymbol(){return _T("rand"); }



  virtual MTSTRING getHelpString(){ return _T("rand(min, max)"); }

  virtual MTSTRING getDescription()

      { return _T("Random value between min and max"); }

  virtual int getNbArgs(){ return 2; }



  virtual bool isConstant(){ return false; }



  virtual MTDOUBLE evaluate(unsigned int nbArgs, const MTDOUBLE *pArg)

  {

    return pArg[0]+(rand()/(double)RAND_MAX)*(pArg[1]-pArg[0]); 

  }



  virtual MTFunctionI* spawn(){ return new RandMinMaxFct(); }

};
public class MySumFunction : IMTFunction

{

  public double evaluate0()

  {      

    throw new Exception("The method or operation is not implemented.");

  }



  public double evaluate1(double arg)

  {

    return arg;

  }



  public double evaluate2(double arg, double arg2)

  {

    return arg + arg2;

  }



  public double evaluate3(double arg, double arg2, double arg3)

  {

    return arg + arg2 + arg3;

  }



  public double evaluate(Array pArgs)

  {

    double sum = 0;

    for (int t = 0; t < pArgs.Length; t++)

    {

      sum += (double)pArgs.GetValue(t);

    }



    return sum;

  }



  public string getDescription()

  {

    return "Computes the sum of many values";

  }



  public string getHelpString()

  {

    return "slowsum(x,y,z,...)";

  }



  public int getNbArgs()

  {

    return -1;

  }



  public string getSymbol()

  {

    return "slowsum";

  }

}
MTParser parser = new MTParser();

parser.defineFunc(new MySumFunction());
MTParser parser;

parser.defineMacro(_T("euc(x,y)"), _T("sqrt(x^2+y^2)") , 

          _T("Euclidean distance"));
Dim parser As New MTParser

parser.defineMacro "euc(x,y) ", "sqrt(x^2+y^2)" , "Euclidean distance"
{A75}{A76}{A77}{A78} {A79}{A80} {S11} 德尔福彗星爪哇爪哇爪哇彗星彗星彗星 彗星COM ñŸŸŸŸŸñŸŸñŸŸñŸñŸ美元美元美元 美元问问美元美元美元美元美元美元免费免费 ? 涝?br>源代码美元N / A美元美元免费免费N / AN / A{S12}



















亲切的问候,


的问候,

的问候,
谢谢!

的问候,

的问候,













感谢

的问候,






&# 160;


的问候,
关于作者:


中国
我是一名编程爱好者,
谢谢orcode.com为我们提供一个学习和分享的平台。
有什么问题。可以就本内容回复,我看到时。会尽量回复的。
 文章分类
 桌面
 网页开发
 移动开发
 数据库
 多媒体
 编程语言
 平台,框架和库
 编程通用
 图形/设计
 开发周期
 一般阅读
 第三方产品
 作者资源
 其他
快速解答标签
c x 6850
VC x 7405