VB.NET 中的多项式数学解析器





5.00/5 (10投票s)
VB.NET 中的多项式数学解析器和计算器
引言
在许多情况下,可能存在一个包含数学表达式的 string
,例如“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
类。 '令牌化'工作由正则表达式模式完成。
令牌
令牌组是
numbers <num>
operators <op>
logical operators <lop>
functions <fn>
functions <vfn> functions retreiving a complex or polynomial array
constants <cnt>
variables <var>
any other character <any>
besides end of tokens <end> formed by an escape character Chr(27).
模式看起来像
(?s)(?<num>((\d{1,3}((\,\d{3})+(?!\d))(\.[0-9]+)?)|[\.\d]+)([eE](\s*)[-+]?[0-9]+)?)(?-s)|
(?<op>[-+*/\^])|
(?<lop>nand|mod|and|nor|xor|not|or|%|!)(?![a-zA-Z_]+)|
(?i)(?<fn>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)(?<vfn>roots|(?<fct>factorize|factors|factor)(?-i))(?![a-zA-Z_]+)|
(?<cnt>e|(?i)pi(?-i))(?![a-zA-Z_]+)|
\(|\)|
(?<vars>\w)+|(?<end>\e)+|
(?<any>[^\s←\,\.])+|(?<any>\,|\.)+
例如,尾随的 '(?![a-zA-Z_]+)
' 在 <cnt>
中允许使用 'epsilon
' 或 'cosA
' 等变量,而不会干扰常量、逻辑运算符和函数。
函数 roots
返回一个包含输入多项式根的复数数组。函数 factor
返回输入多项式的因子数组。输入也可以是 (分子多项式)/(分母多项式)
的形式。
Using the Code
有两种可能的实例化方式
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()
方法之一完成的。
第一种方法
'// argument is a string:
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' variable, 2 exponent (a^2)
polyA += New Polynomial(-1.0) ' // a ^ 2 - 1
eP.vars.Add("y", polyA)
'// argument is a string:
Dim cplx As Complex = eP.Evaluate("x*(y-i*5)")
...
解析 string
后,可以调用重载的第二个方法
'// change "x" value (change any variable value):
eP.vars.Item("x") = New Polynomial(3)
'// argument is the 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) + "</br>"
Else
s1 += "-------------------</br>"
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) + "</br>"
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()
中,并且一个空元素将把因子与分子和分母分开。
您可以调用 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
”一词来显示操作步骤。
基本原理
解析方法是递归下降解析:通过递归下降解析表达式。
评估方法 E
为任何加法或减法调用 T
,但 T
首先为任何乘法或减法调用 F
,而 F
首先为任何可能的幂运算调用 P
。 P
首先调用 v
以获取下一个令牌。 如果存在“(
”令牌,则 v
递归调用 T
。
E --> T {( "+" | "-" ) T}
T --> F {( "*" | "/" ) F}
F --> P ["^" F]
P --> v | "(" E ")" | "-" T
分步演示
这里介绍的算法将 T
和 F
合并到一个方法中。此外,方法 v
运算任何可能的函数,如 cos()
、csc()
、mod
等等。
在撰写本文时,我发现了一些小故障。如果您发现任何其他错误,请告诉我。
历史
- 2022 年 4 月 3 日:初始版本