/ParserNG

ParserNG is a powerful math tool that parses and evaluates math expressions, does differential calculus(symbolic) evaluations, numerical integration, Equation solving, statistics amongs other functionality

Primary LanguageJavaApache License 2.0Apache-2.0

ParserNG

ParserNG is a powerful open-source math tool that parses and evaluates algebraic expressions.

It was created in 2009 by me, Gbemiro Jiboye and later used as a critical part of my final year project at the Department of Computer Science and Engineering, Obafemi Awolowo University,Ile-Ife, Osun State, Nigeria.

My goal was to create a simple, yet powerful, not too bogus math tool that scientists and developers can deploy with their work to solve problems of all ranges--from simple to complex.

FEATURES

  1. Arithmetic operations.
  2. Statistical operations
  3. Trigonometric operations
  4. Permutations and Combinations
  5. Basic matrix operations
  6. Differential Calculus(Exact numerical accuracy achieved using symbolic differentiation)
  7. Integral Calculus(Numerical)
  8. Quadratic Equations
  9. Tartaglia's Equations( or generally: a.x3+b.x+c = 0 )
  10. Numerical (Iterative) solution for roots of equations
  11. Simultaneous Linear Equations
  12. Amongst others
  13. Variables creation and usage in math expressions
  14. Function creation and usage in math expressions

Using ParserNG

The simplest way to evaluate an expression in ParserNG is to use the MathExpression class. MathExpression is the class responsible for basic expression parsing and evaluation.

Do:
MathExpression expr = new MathExpression("r=4;r*5");
System.out.println("result: " + expr.solve());

What does this do?

It creates a variable called rand sets its value to 4. Then it goes ahead to evaluate the expression r*5 and returns its value when expr.solve() is called.
The print statement would give

solution: 20.0

at the console.

Some key applications of parsers involve repeated iterations of a given expression at different values of the variables involved. Iteratively determining the roots of an equation, graphing etc.

For repeated iterations of an expression over a value range, say 'x^2+5*x+1', the wrong usage would be:


for(int i=0;i<10000;i++){

double x = i;
MathExpression expression = new MathExpression("x="+i+";x^2+5*x+1");
expression.solve();
}

The MathExpression constructor basically does all the operations of scanning and interpreting of the input expression. This is a very expensive operation. It is better to do it just once and then run the solve() method over and over again at various values of the variables.

For example:


MathExpression expression = new MathExpression("x^2+5*x+1");

for(int i=0; i<100000; i++){
expression.setValue("x", String.valueOf(i) );
expression.solve();
}

This ensures that the expression is parsed once(expensive operation) and then evaluated at various values of the variables. This second step is an high speed one, sometimes taking barely 3 microseconds on some machines.

Inbuilt Functions
The parser has its own set of built-in functions. They are: sin,cos,tan,sinh,cosh,tanh,sin-¹,cos-¹,tan-¹,sinh-¹,cosh-¹,tanh-¹,sec,csc,cot,sech,csch,coth,sec-¹,csc-¹,cot-¹,sech-¹,csch-¹,coth-¹,exp,ln,lg,log,ln-¹,lg-¹,log-¹,asin,acos,atan,asinh,acosh,atanh,asec,acsc,acot,asech,acsch,acoth,aln,alg,alog,floor,ceil,sqrt,cbrt,inverse,square,cube,pow,fact,comb,perm,sum,prod,avg,med,mode,rng,mrng,rms,cov,min,max,s_d,variance,st_err,rnd,sort,plot,diff,intg,quad,t_root,root,linear_sys,det,invert,tri_mat,echelon,matrix_mul,matrix_div,matrix_add,matrix_sub,matrix_pow,transpose,matrix_edit,

Note that alternatives to many functions having the inverse operator are provided in the form of an 'a' prefix. For example the inverse sin function is available both as sin-¹ and as asin

User defined functions
You can also define your own functions and use them in your math expressions. This is done in 2 ways:

  1. f(x,a,b,c,...)= expr_in_said_variables
    For example: f(x,y)=3*x^2+4*x*y+8
  2. f = @(x,a,b,c,...)expr_in_said_variables
    For example: f= @(x,y)3*x^2+4*x*y+8

Your defined functions are volatile and will be forgotten once the current parser session is over. The only way to have the parser remember them always is to introduce some form of persistence.

So for instance, you could pass the following to a MathExpression constructor:

f(x)=sin(x)+cos(x-1)
Then do: f(2)....the parser automatically calculates sin(2)+cos(2-1) behind the scenes.

Differential Calculus

ParserNG makes differentiating Math Expressions really easy.

ParserNG uses its very own implementation of a symbolic differentiator.

It performs symbolic differentiation of expressions behind the scenes and the computes the differential coefficient of the function at some supplied x-value.

To differentiate a function, do:


  MathExpression expr = new MathExpression("diff(@(x)x^3,3,1)"); 
  
  System.out.println(ex.solve());
  

This will print:

27.0

More Examples

Evaluating an expression is as simple as:

MathExpression expr = new MathExpression("(34+32)-44/(8+9(3+2))-22"); 

System.out.println("result: " + expr.solve()); 

This gives: 43.16981132075472

Or using variables and calculating simple expressions:

MathExpression expr = new MathExpression("r=3;P=2*pi*r;"); 

System.out.println("result: " + expr.getValue("P")); 

Or using functions:

MathExpression expr = new MathExpression("f(x)=39*sin(x^2)+x^3*cos(x);f(3)"); 
System.out.println("result: " + expr.solve()); 

This gives: -10.65717648378352

Derivatives (Differential Calculus)

To evaluate the derivative at a given point(Note it does symbolic differentiation(not numerical) behind the scenes, so the accuracy is not limited by the errors of numerical approximations):

MathExpression expr = new MathExpression("f(x)=x^3*ln(x); diff(f,3,1)"); 
System.out.println("result: " + expr.solve()); 

This gives: 38.66253179403897

The above differentiates x^3 * ln(x) once at x=3. The number of times you can differentiate is 1 for now.

For Numerical Integration:

MathExpression expr = new MathExpression("f(x)=2*x; intg(f,1,3)"); 
System.out.println("result: " + expr.solve()); 

This gives: 7.999999999998261... approx: 8 ...

I will talk about other functionalities of the library, such as numerical integration later on! Thanks.