数学表达式解析器

在许多情况下,可能会遇到包含数学表达式的字符串,例如 "1+2*5"、"(3+i)(3-i)" 或 "(z^2*w+4z^3w-w^2-4z*w^2)/(w+4z*w)",并且需要进行计算以得到结果。也许需要根据不同的变量值来计算结果,而结果可能是另一个多项式。在这些情况下,这里介绍的多项式解析器可能会有所帮助。

这里的类是完全免费且可下载的计算机代数系统(CAS)计算器的一小部分,但有所改进。其中一个目标是这些类不依赖于其他“外部”类,就像在CAS计算器中发生的那样。

七个类

类 'Msg10' 只包含一些用于处理可能的错误的消息。类 'G10' 包含像正则表达式模式这样的全局成员。类 'Rational' 提供了更精确的操作。类 'Complex' 执行复数数学运算。类 'Polynomial' 操作多项式。类 'Roots' 寻找多项式的根和因子。类 'parsePolynomial' 负责将输入字符串分割成标记,并相应地调用 Roots、Polynomial 或 Msg10 类。Roots 依赖于 Polynomial 类,而 Polynomial 又依赖于 Complex,Complex 依赖于 Rational。'标记化'工作由正则表达式模式完成。

标记

标记组包括:

  • 数字
  • 运算符
  • 逻辑运算符
  • 函数
  • 函数 返回复数或多项式数组的函数
  • 常量
  • 变量
  • 任何其他字符
  • 除了由转义字符 Chr(27) 形成的结束标记

正则表达式模式如下所示:

(?s)(?((\d{1,3}((\,\d{3})+(?!\d))(\.[0-9]+)?)|[\.\d]+)([eE](\s*)[-+]?[0-9]+)?)(?-s)| (?[-+*/\^])| (?nand|mod|and|nor|xor|not|or|%|!)(?![a-zA-Z_]+)| (?i)(?logtwo|logten|acosh|acoth|acsch|asech|asinh|atanh|floor|round|norm|conj| coth|csch|sech|acos|acot|acsc|asec|asin|atan|cosh|sign|sinh|sqrt|tanh|abs|cos|cot| csc|exp|log|sec|sin|sqr|tan|ln|re|im(?-i))(?![a-zA-Z_]+)| (?i)(?roots|(?factorize|factors|factor)(?-i))(?![a-zA-Z_]+)| (?e|(?i)pi(?-i))(?![a-zA-Z_]+)| \(|\)| (?\w)+|(?\e)+| (?[^\s←\,\.])+|(?\,|\.)+

函数

函数 'roots' 返回包含输入多项式根的复数数组。函数 'factor' 返回输入多项式的因子数组。输入也可以是形式 (分子多项式)/(分母多项式)。

使用代码

有两种实例化方式:

Dim eP As New ParsePolynomial eP.CultureInfo = New Globalization.CultureInfo("fr-FR") ... Dim eP As New ParsePolynomial(New Globalization.CultureInfo("es-AR")) ...

默认情况下,CultureInfo 设置为 "en-US"。

通过调用两个 'Evaluate()' 方法之一进行评估。第一种方法:

Dim poly As Polynomial = eP.Evaluate("(x-1)*(x+1)") ...

第一种方法带有变量,设置在 Dictionary(Of String, Polynomial) 中:

Dim eP As New ParsePolynomial eP.vars.Add("x", New Polynomial(Complex.one)) Dim polyA As New Polynomial("a", 2) ' // 'a' 变量,2 指数 (a^2) polyA += New Polynomial(-1.0) ' // a ^ 2 - 1 eP.vars.Add("y", polyA) ' // 参数是字符串: Dim cplx As Complex = eP.Evaluate("x*(y-i*5)") ...

一旦字符串被解析,可以调用重载的第二种方法:

' // 更改 "x" 值(更改任何变量值): eP.vars.Item("x") = New Polynomial(3) ' // 参数是 Dictionary(Of String, Polynomial): Dim polyC As Polynomial = eP.Evaluate(eP.vars) ...

变量名以字母或下划线 (_) 开头,可以包含字母、数字或下划线,并且可以是任何长度。当然,如果不需要解析器,可以直接调用 Polynomial 类。

输出

输出可以只是一个 Polynomial,一个 Complex() 数组,或者一个 Polynomial() 数组:

Dim t1 As Int64 = Now.Ticks Dim p As Polynomial = eP.Evaluate(TBExpression.Text) Dim t2 As New TimeSpan(Now.Ticks - t1) If eP.vPoly.Length Then ' Response is an array of Polynomials ? Dim s1 As String = "" For i As Int32 = 0 To eP.vPoly.Length - 1 If eP.vPoly(i) IsNot Nothing Then s1 += eP.vPoly(i).ToStringPolynomial(eP.Decimals, eP.Imaginary, eP.CultureInfo) + " " Else s1 += " -------------------" End If Next NavigateToString(s1) ' Show in Webbrowser1 ElseIf eP.vRoots.Length Then ' Response is an array of Complex ? Dim s1 As String = "" For i As Int32 = 0 To eP.vRoots.Length - 1 s1 += eP.vRoots(i).ToStringComplex(eP.Decimals, eP.Imaginary, eP.CultureInfo) + " " Next NavigateToString(s1) ' Show in Webbrowser1 Else ' Response is a Polynomial NavigateToString(p.ToStringPolynomial(eP.Decimals, eP.Imaginary, eP.CultureInfo)) End If

当调用 eP.Evaluate("factor(numerator)/(denominator)") 时,返回将在 eP.vPoly() 中,并且一个 null 元素将因子与分子和分母分开。

可以调用 Polynomial.ToString() 或 ToStringPolynomial(Optional numDecimals As Int32 = 15, Optional sImg As String = "i", Optional cultureInfo As Globalization.CultureInfo = Nothing) As String:

... polyC.ToStringPolynomial(4, eP.Imaginary, eP.CultureInfo) ...

详细版本将通过在单词 'detail' 前面添加操作步骤来显示。

基本原则

这里介绍的算法将 T 和 F 包含在单个方法中。此外,方法 v 操作任何可能的函数,如 cos()、csc()、mod 等。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485