fparser
A JavaScript Formula Parser
fparser provides a Formula class that parses strings containing mathematical formulas (e.g. x*sin(PI*x/2)
) into an evaluationable object.
One can then provide values for all unknown variables / functions and evaluate a numeric value from the formula.
For an example application, see https://fparse.alexi.ch/.
Features
Parses a mathematical formula from a string. Known expressions:
- Numbers in the form [-]digits[.digits], e.g. "-133.2945"
- simple operators: '+','-','*','/', '^' expanded in correct order
- parentheses '(', ')' for grouping (e.g. "5*(3+2)")
- all JavaScript Math object functions (e.g. "sin(3.14)")
- all JavaScript Math constants like PI, E
- the use of own functions
- the use of single-char variables (like '2x')
- the use of named variables (like '2*[myVar]')
- memoization: store already evaluated results for faster re-calcs
- use it in Web pages, as ES6 module or as NodeJS module
- Example:
-1*(sin(2^x)/(PI*x))*cos(x))
Usage
<script src="dist/fparser.js"></script>
Install:
$ npm install --save fparser
Use:
const Formula = require('./fparser');
or:
import Formula from 'fparser';
const fObj = new Formula('2^x');
let result = fObj.evaluate({x: 3});
let results = fObj.evaluate([{x: 2},{x: 4},{x: 8}]);
let result = Formula.calc('2^x',{x: 3});
let results = fObj.calc('2^x',[{x: 2},{x: 4},{x: 8}]);
const Formula = require('./fparser');
const fObj = new Formula('2^x)');
More options
Using multiple variables
const fObj = new Formula('a*x^2 + b*x + c');
let result = fObj.evaluate({a:2,b:-1,c:3,x:3});
Using named variables
Instead of single-char variables (like 2x+y
), you can also use named variables in brackets:
const fObj = new Formula('2*[var1] + sin([var2]+PI)');
let result = fObj.evaluate({var1: 5, var2: 0.7});
Using user-defined functions
const fObj = new Formula('sin(inverse(x))');
fObj.inverse = (value) => 1/value;
let results = fObj.evaluate({x: 1,x:2,x:3});
let result = fObj.evaluate({
x: 2/Math.PI,
inverse: (value) => (-1*value)
});
If defined in the value object AND on the formula object, the Value object has the precedence
Re-use a Formula object
You can instantiate a Formula object without formula, and set it later, and even re-use the existing object:
const fObj = new Formula();
fObj.setFormula('2*x^2 + 5*x + 3');
let res = fObj.evaluate({x:3});
fObj.setFormula('x*y');
res = fObj.evaluate({x:2, y:4});
Memoization
To avoid re-calculation of already evaluated results, the formula parser object supports memoization:
it stores already evaluated results for given expression parameters.
Example:
const fObj = new Formula('x * y', {memoization: true});
let res1 = fObj.evaluate({x:2, y:3});
let res2 = fObj.evaluate({x:2, y:3});
You can enable / disable memoization on the object:
const fObj = new Formula('x * y');
let res1 = fObj.evaluate({x:2, y:3});
fObj.enableMemoization();
let res2 = fObj.evaluate({x:2, y:3});
let res3 = fObj.evaluate({x:2, y:3});
Get all used variables
const f4 = new Formula('x*sin(PI*y) + y / (2-x*[var1]) + [var2]');
console.log(f4.getVariables());
Get the parsed formula string
After parsing, get the formula string as parsed:
const f = new Formula('x * ( y + 9 )');
console.log(f.getExpressionString());
Changelog
2.0.0
This release is a complete re-vamp, see below. it should be completely backward compatible to the 1.x versions, but I did not test all
edge cases.
- Switched to MIT license
- complete refactoring of the parsing and evaluating part: The parser now creates an Expression Tree (AST) that saves extra time while evaluating - Evaluation now only traverses the AST, which is much faster.
- added
getExpressionString()
function to get a formatted string from the formula - adding support for memoization: store already evaluated results
- Switched bundler to webpack
- fixed some parser bugs
1.4.0
- Adding support for named variables (
2x + [var1]
) - switched testing to chromium runner instead of PhantomJS
1.3.0
- modernized library: The source is now ES6 code, and transpiled in a dist ES5+ library.
- Make sure you include dist/fparser.js if you are using it as a browser library.
- Drop support for Bower, as there are more modern approaches (npm) for package dependency nowadays
License
Licensed under the MIT license, see LICENSE file.