在许多情况下,可能会遇到包含数学表达式的字符串,例如 "1+2*5" 或 "(3+i)(3-i)",并且需要进行计算以得到结果。此外,在处理像 "0.5*x+4" 这样的公式时,可能需要为不同的 x 值计算结果。在这些情况下,这里介绍的复杂解析器可能会有所帮助。
这些类是完全免费且可下载的计算机代数系统(CAS)计算器的一部分,但已经进行了改进。其中一个目标是这些类不依赖于其他“外部”类,就像在CAS计算器中那样。
类 Global10
包含全局值,如小数位数、虚数字符(i 或 j)或 CultureInfo
。
类 Msg10
仅包含一些用于处理可能错误的消息。
类 Rational
在操作中提供了更多的精度。
类 Complex
执行复数数学运算。
类 parseComplex
负责将输入字符串分割成标记,并相应地调用 Complex
或 Msg10
类。类 Complex
利用类 Rational
为其实部和虚部成员。“标记化”工作由正则表达式模式完成。
标记组包括:
<mode>
<num>
<op>
<lop>
<fn>
<cnt>
<var>
<any>
<end>
由转义字符 Chr(27) 形成。模式看起来像:
(?i)(?<mode>(&dec(?<dec>\d{1,2})|&(rad|deg|grad|[hobdij])))(?-i)
(?<numop>(?<num>((\d{1,3}((\,\d{3})+(?!\d))(\.[0-9]+)?)|[\d]{1}[\.\dA-Fa-f]*)([eE](\s*)[-+]?[0-9]+)?)|
(?<op>[-+*/\^]))|\(|\)|
(?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)(?![a-zA-Z_]+)|
(?<lop>\<\<|\>\>|nand|mod|and|nor|xor|not|or|%|!)(?![a-zA-Z_]+)|
(?<cnt>e|(?i)pi)(?![a-zA-Z_]+)|
(?<vars>[_a-zA-Z]\w*)+|(?<end>\e)+|
(?<any>[^\s←\,\.])+|(?<any>\,|\.)+
数字的模式,取决于 Globalization.CultureInfo
设置,可能会交换点(NumberFormat.NumberDecimalSeparator)和逗号(NumberFormat.NumberGroupSeparator)。
模式允许以十六进制、十进制、八进制或二进制基数输入数字;同时设置小数位数和虚数字符。
有两种可能的实例化方式:
Dim eP As New ParseComplex
eP.CultureInfo = New Globalization.CultureInfo("fr-FR")
...
Dim eP As New ParseComplex(New Globalization.CultureInfo("es-AR"))
...
默认情况下,CultureInfo
设置为 "en-US"。
通过调用两个 Evaluate()
方法之一进行评估。
第一种方法:
' 参数是一个字符串:
Dim cplx As Complex = eP.Evaluate("(3+5*i)*(3-i*5)")
第一种方法带有变量,设置在 Dictionary(Of String, Complex)
中:
eP.vars.Add("x", Complex.one)
eP.vars.Add("y", New Complex(-1, 2))
' 参数是一个字符串:
Dim cplx As Complex = eP.Evaluate("(3+x*i)*(y-i*5)")
一旦字符串被解析,可以调用重载的第二种方法:
' 更改 "x" 的值(更改任何变量的值):
eP.vars.Item("x") = New Complex(3)
' 参数是 Dictionary(Of String, Complex):
Dim cplx As Complex = eP.Evaluate(eP.vars)
变量名以字母或下划线 (_) 开头,可以包含字母、数字或下划线,并且可以是任何长度。
当然,如果不需要解析器,可以直接调用 Complex
类。
默认的数值基数是十进制。要更改为其他基数,请写 &h(十六进制),&o(八进制)或 &b(二进制)。附加 &d 将恢复为十进制基数。
以类似的方式,°,&grad 将接受以度或格令为单位的角度。要恢复为默认的弧度,请输入 &rad。
要更改默认的虚数 i 为 j,请写 &j,要恢复为默认字符,请写 &i。
例如,输入 &culture it-IT 将更改当前的 CultureInfo
为 it-IT。因此,输入和输出将按照文化进行。
可能的修饰符示例如下:
Dim cplx As Complex = eP.Evaluate("&culture fr-FR &dec2 &h 0f + &j &d 0,2+0,3*j")
Console.WriteLine(cplx.ToString)
将显示 15,2+j*0,3
可以调用 Complex.ToString()
或 ToStringComplex(numDecimals As Int32, sImg As String, cultureInfo As Globalization.CultureInfo) As String
:
cplx.ToStringComplex(4, eP.Imaginary, eP.CultureInfo)
如果找到单词 detail,代码将输出操作步骤。例如:
Dim cP As New ParseComplex
Dim cplx As Complex = cP.Evaluate("detail (2+i*3)*(1+i)")
Console.WriteLine(cP.GetDetail)
将输出:
[ (2+i*3)*(1+i) ]
[2*1 - 3*1 + i*(2*1+3*1) ]
[-1+i*5]
这里介绍的解析方法是递归下降解析:解析表达式通过递归下降。
评估方法 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 操作逻辑操作符,'%' 和 mod 任何可能的函数,如 cos(),csc() 等。