Math Expressions Interpreter

Introduction

I’ve ported from C++ to C# my old expression interpreter. It’s written from scratch without any parser generators like, say, ANTLR. Maybe it isn’t the modern approach but I’m using this code during last twenty years or so.

Basics

An expression contains parameters, numeric and predefined symbolic constants, predefined functions calls.

All elements type is treated as double. Evaluation result is also double (having, possibly, special values NaN, INF, -INF).

Samples:

  • (1+2)*5
  • 2*sqrt(4)
  • if({0}-4,{0}-10,33,{0}+10)

Usage

Expression class constructor takes an expression string as a parameter and parses it into the tree of operations. Exceptions of some types could be thrown during parsing.

Then the expression could be evaluated multiple times with different parameters set with the Evaluate method. Evaluation is always successful (doesn’t throws exceptions) although the result could be one of the double type special values mentioned above.

Constants

An expression can contain numeric literals and predefined symbolic constants (like "PI").

The decimal point is used as the separator in literals. Scientific notation ‘e’ or ‘E’ can be used.

Predefined Constants

The following symbolic constant names are defined:

  1. Natural logarithm base "e" = 2.71…
  2. "PI" = 3.14…
  3. Not-a-number value "NaN".
  4. Positive infinity "Inf".
  5. Negative infinity "NInf".

Constant names are case-insensitive.

Parameters

Expression parameters (variables) are denoted with the placeholder syntax {index} like in the string.Format method format string. The ‘index’ is the parameter position in the array passed to the Evaluate method call. If the parameter at the specified index is missed the NaN value used.

Operations

Operations priorities are as follows (the top is highest).

  1. Function calls and parentheses ().
  2. Unary plus (+) and minus (-).
  3. Exponentiation (^).
  4. Multiplication (*), division (/), modulus (%).
  5. Addition (+) and subtraction (-).

Parentheses

Any level parentheses used to group the operations.

Function calls

All functions return double value and can have one or more arguments. Syntax: function(arg1, arg2, …). Argument itself also could be an expression. Some functions can have variable argument count.

Unary plus and minus

Unary plus is ignored. Unary minus is right associative, i.e. –x means (-(-x)). When Unary minus is applied to an infinity its sign changes to the opposite (e.g. Inf becomes NInf and vice versa).

Exponentiation

Pow function analog. The operation is right associative, i.e. x^y^z means (x^(y^z)).

Any values except NaN powered to 0 equal to 1. NaN at any power equal to NaN.

Multiplication, division, modulus

These operations are left associative, i.e. x*y/z means ((x*y)/z).

Addition and subtraction

These operations are left associative, i.e. x+y-z means ((x+y)-z).

Functions

Function names are case-insensitive.

Conditional Functions

Conditional functions allow emulate a branching in the intrinsically linear expression syntax.

First argument value of any conditional function is compared to the branching condition defined by that function. Depending on the comparison result one of the other arguments is calculated.

Branching by sign (If)

If function has 4 or 5 arguments.

If(cond, var1, var2, var3)

or

If(cond, var1, var2, var3, spec)

If function checks the cond argument has a special value. If so, two variants are possible:

  • If the spec argument exists it’s calculated.
  • Otherwise the function returns the value of cond, i.e. NaN, Inf or NInf.

If the cond argument doesn’t have a special value, If function calculates and returns the value of one of three arguments.

  1. var1 on cond < 0
  2. var2 on cond == 0
  3. var3 on cond > 0

Branching by special value (IfNotFinite)

IfNotFinite function has 2 or 3 arguments.

IfNotFinite(cond, spec)

or

IfNotFinite(cond, spec, var)

If the cond argument has a special value the function calculates and returns the spec argument value. Otherwise, if var argument exists the function calculates and returns it. Else it returns the cond value.

Branching by NaN (IfNaN)

IfNaN function has 2 or 3 arguments.

IfNaN(cond, spec)

or

IfNaN(cond, spec, var)

If the cond argument value is NaN the function calculates and returns the spec argument value. Otherwise, if var argument exists the function calculates and returns it. Else it returns the cond value.

Branching by Infinity (IfInf)

IfInf function has 2 or 3 arguments.

IfInf(cond, spec)

or

IfInf(cond, spec, var)

If the cond argument value is Inf or NInf the function calculates and returns the spec argument value. Otherwise, if var argument exists the function calculates and returns it. Else it returns the cond value.

Branching by Positive Infinity (IfPInf)

IfPInf function has 2 or 3 arguments.

IfPInf(cond, spec)

or

IfPInf(cond, spec, var)

If the cond argument value is Inf the function calculates and returns the spec argument value. Otherwise, if var argument exists the function calculates and returns it. Else it returns the cond value.

Branching by Negative Infinity (IfNInf)

IfNInf function has 2 or 3 arguments.

IfNInf(cond, spec)

or

IfNInf(cond, spec, var)

If the cond argument value is NInf the function calculates and returns the spec argument value. Otherwise, if var argument exists the function calculates and returns it. Else it returns the cond value.

Math Functions

Absolute value Abs

Abs has one argument and returns its absolute value. The same is applied to the negative infinity: Inf is returned in place of NInf.

Square root Sqrt

Sqrt has one argument and returns its square root. The square root of negative number, including negative infinity, and NaN, is NaN. The square root of Inf is Inf.

The Sqrt(x) is the analog of Pow(x, 0.5).

Exponentiation Pow

Pow has two arguments and returns the first argument raised to the power of the second argument. It’s the analog of ^ operation.

Any value except NaN at the power of 0 is equal to 1. NaN at any power is equal to NaN.

Logarithms

Log and Log10 functions has one argument. Logarithm of 0 is equal to NInf. Logarithm of negative argument is NaN.

Thrigonometric functions

Sin, Cos and Tan functions has one argument. If the argument has any special value the result will be NaN.

Reverse thrigonometric functions

Asin, Acos and Atan functions has one argument and return the angle value in radians or a special value.

If Asin or Acos argument is outside of [-1,1] or has a special value the result will be NaN.

If Atan argument has a special value the result will be:

  1. NaN for NaN
  2. pi/2 for Inf
  3. -pi/2 for NInf

Hyperbolic functions

Sinh, Cosh and Tanh functions has one argument.

The code

You can download the code here:

http://cid-39d56f0c7a08d703.skydrive.live.com/embedrow.aspx/.Public/Expression/Expression030609.zip

 

Regards,
Oleg V. Polikarpotchkin

Advertisements

About ovpwp

I am engaged in programming, maintenance and supply of computing technique since 1970. Started with the computers M, BESM, Minsk series and received appropriate education in the least, in which it was then possible in THE USSR. Then he went the usual way - ES series, IBM 360/370, Sun Spark, Ibm Power & PS2, PC. Programming started in the code (machine commands), then were sorts of assemblers, Algol, FORTRAN, PL/1, C, C , VB, C#. It is only the ones that I used the production scale; but there were, of course, others like List, Modula, Pascal, Java, etc. Currently I prefer .NET platform for desktop development. I don't really like web-programming (probably because of the inability for quality design), but I have enough experience in site building in LAMP environment using PHP.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s