Complex Math Parser and Evaluator in VB.NET
source link: https://www.codeproject.com/Articles/5328357/Complex-Math-Parser-and-Evaluator-in-VB-NET
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Introduction
In many situations, there may be a string
containing a math expression, such as "1+2*5
" or "(3+i)(3-i)
", and there is the need to do the math and calculate the result. Also, in case of a formula like "0.5*x+4
", we may need to calculate the result for several different values of x
. In those situations, the complex parser presented here may help.
The classes here are a small part -but improved- of my all free and downloadable CAS calculator http://xrjunque.nom.es. One of the goals is that these classes do not rely on other 'external' classes as happens in the CAS calculator.
The Four Classes
- Class '
Msg10
' just contains a few messages to handle possible errors. - Class '
Rational
' gives a bit more of accuracy in the operations. - Class '
Complex
' class does the complex math. - Class '
parseComplex
' is in charge of dividing the input string into tokens and call accordingly to classesComplex
orMsg10
. ClassComplex
makes use of classRational
for its Real and Imaginary members. The 'tokenizing' job is done by a Regex pattern.
Tokens
The tokens groups are:
numbers <num> operators <op> logical operators <lop> functions <fn> constants <cnt> variables <var> any other character <any> besides end of tokens <end> formed by an escape character Chr(27).
The pattern looks like:
(?<end>\e)+| (?<numop> (?<num>((\d{1,3}((\,\d{3})+(?!\d))(\.[0-9]+)?)|[\.\d]+)([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)| (?<lop>nand|mod|and|nor|xor|not|or)| (?<cnt>e|(?i)pi)| (?<vars>\w+)| (?<any>[^\s?\,\.])+|(?<any> \,|\.)+
Pattern for numbers, depending on the Globalization.CultureInfo
setting, may swap the dot (NumberFormat.NumberDecimalSeparator
) and the comma (NumberFormat.NumberGroupSeparator
).
Using the Code
The are two possible ways of instantiation:
Dim eP As New ParseComplex eP.CultureInfo = New Globalization.CultureInfo("fr-FR") ... Dim eP As New ParseComplex(New Globalization.CultureInfo("es-AR")) ...
By default, CultureInfo
is set to "en-US
".
Evaluation is done by calling one of the two Evaluate()
methods.
First method:
'// argument is a string: Dim cplx As Complex = eP.Evaluate("(3+5*i)*(3-i*5)") ...
First method with variables, set in a Dictionay(Of String, Complex)
:
eP.vars.Add("x", Complex.one) eP.vars.Add("y", New Complex(-1, 2)) '// argument is a string: Dim cplx As Complex = eP.Evaluate("(3+x*i)*(y-i*5)") ...
Once the string
has been parsed, it is possible to call the overloaded second method:
'// change "x" value (change any variable value): eP.vars.Item("x") = New Complex(3) '// argument is the Dictionary(Of String, Complex): Dim cplx As Complex = eP.Evaluate(eP.vars) ...
Variables names start with a letter or underscore (_
), can contain letters, numbers or underscore and can be any length.
Of course, you may call the Complex
class directly, if you don't need the parser.
The Output
You may call Complex.ToString()
or ToStringComplex(Optional numDecimals As Int32 = 15, Optional sImg As String = "i", Optional cultureInfo As Globalization.CultureInfo = Nothing) As String
:
... cplx.ToStringComplex(4, eP.Imaginary, eP.CultureInfo) ...
Basic Principles
The parsing method is a recursive-descent parsing: Parsing Expressions by Recursive Descent.
Evaluation method E
calls T
for any addition or substraction, but T
calls first F
for any multiplication or substraction, and F
calls first P for any power possible power operation. P
calls first v
to get next token. If there is a "(
" token, v
calls recursively to T
.
E --> T {( "+" | "-" ) T} T --> F {( "*" | "/" ) F} F --> P ["^" F] P --> v | "(" E ")" | "-" T
Step by Step Walk-throughs
Algorithm presented here englobes T
, F
, and P
in a single method. Besides, method v
operates any possible function like cos()
, csc()
and so on.
While writing this article, I found some glitches. If you find any further error, please let me know.
History
- 25th March, 2022: Initial version
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK