解析复数表达式

在许多情况下,可能会遇到包含数学表达式的字符串,例如 "1+2*5" 或 "(3+i)(3-i)",并且需要进行计算以得到结果。此外,在处理像 "0.5*x+4" 这样的公式时,可能需要为不同的 x 值计算结果。在这些情况下,这里介绍的复杂解析器可能会有所帮助。

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

五个类

Global10 包含全局值,如小数位数、虚数字符(i 或 j)或 CultureInfo

Msg10 仅包含一些用于处理可能错误的消息。

Rational 在操作中提供了更多的精度。

Complex 执行复数数学运算。

parseComplex 负责将输入字符串分割成标记,并相应地调用 ComplexMsg10 类。类 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() 等。

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