- Download ParseComplexTesterDetail - 349.2 KB
- Download ParseComplexTester - 303.7 KB
- Download ParseComplex_Csharp - 417.9 KB

## 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 Five Classes

- Class
`Global10`

contains global values like number of decimals, imaginary character (`i`

or`j`

) or`CultureInfo`

. - 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 classes`Complex`

or`Msg10`

. Class`Complex`

makes use of class`Rational`

for its Real and Imaginary members. The 'tokenizing' job is done by a Regex pattern.

## Tokens

The tokens groups are:

mode <mode> 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:

(?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>\,|\.)+ </dec>

Pattern for numbers, depending on the `Globalization.CultureInfo`

setting, may swap the dot (`NumberFormat.NumberDecimalSeparator`

) and the comma (`NumberFormat.NumberGroupSeparator`

).

Mode makes possible to enter numbers in hexadecimal, decimal, octal or binary base; along with setting the number of decimals and the imaginary character.

## 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 default numeric base is decimal. To change to another base write `&h`

(hexadecimal), `&o`

(octal) or `&b`

(binary). Appending `&d`

will restore to decimal base.

In a similar way, `°`

, `&grad`

will accept angles in degrees or in gradians. To restore to default radians, enter `&rad`

.

To change default imaginary `i`

to `j`

, write `&j`

and to turn back to the default character, write `&i`

.

For instance, entering `&culture it-IT`

will change the current `CultureInfo`

to `it-IT`

. So inputs and ouputs will be in mented culture.

An example of possible modificators is the following:

Dim cplx As Complex = eP.Evaluate("&culture fr-FR &dec2 &h 0f + &j &d 0,2+0,3*j" Console.WriteLine(cplx.tostring) ' will show 15,2+j*0,3

## The Output

You may call `Complex.ToString()`

or `ToStringComplex( numDecimals As Int32, sImg As String, cultureInfo As Globalization.CultureInfo) As String`

:

```
cplx.ToStringComplex(4, eP.Imaginary, eP.CultureInfo)
```

## Detail Version

If the word `detail`

is found, code will output operation steps. For example:

Dim cP As New ParseComplex Dim cplx As Complex = cP.Evaluate("detail (2+i*3)*(1+i)") Console.WriteLine(cP.GetDetail) ' Will output: ' [ (2+i*3)*(1+i) ] ' [2*1 - 3*1 + i*(2*1+3*1) ] ' [-1+i*5]

## 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

The algorithm presented here englobes `T `

and `F`

in a single method. Besides, method `v`

operates logical operators, '%' and `mod`

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

- 25
^{th}March, 2022: Initial version