Quick Start

As of version 0.5.0, the library is split into the core and optional modules which can be loaded after the core has been loaded. Only the core is required to evaluate expressions. The modules provide extra functions. See the documentation for the list of functions that each module contains. Some functions depend on more than one module and some modules depend on other modules. Solve for instance depends on both Algebra and Calculus.

This page serves as a quick guide to get up and running. For more detailed documentation see the documentation section.

To get started with nerdamer load the library in your html page or require it using

<script src="nerdamer.core.js"></script> <!-- assuming you've saved the file in the root of course -->
<!-- LOAD MODULES -->
<script src="Algebra.js"></script>
<script src="Calculus.js"></script>
<script src="Solve.js"></script>
<script src="Extra.js"></script> <!-- again assuming you've saved the files in root -->

Or import everything

<script src="all.min.js"></script> <!-- assuming you've saved the file in the root -->;

or if you're using node.js install it using npm i nerdamer and then

// const cannot be used since nerdamer gets modified when other modules are loaded
var nerdamer = require('nerdamer');
// Load additional modules. These are not required.
require('nerdamer/Algebra');
require('nerdamer/Calculus');
require('nerdamer/Solve');
require('nerdamer/Extra');

If you'll be using all modules, you can use a single import

const nerdamer = require("nerdamer/all.min")

Some functions have dependencies from other modules. You can see nerdamer in action at http://www.nerdamer.com/demo All operations are done using the nerdamer object. To add an expression just add it by calling nerdamer object with the expression as the argument. This will return an Expression object.

   
var e = nerdamer('x^2+2*(cos(x)+x*x)');

console.log(e.text());

//result: 
//2*cos(x)+3*x^(2)

You can also pass in an object with known values as the second parameter.

   
        
var e = nerdamer('x^2+2*(cos(x)+x*x)',{x:6});

console.log(e.text());

//result:
//108+2*cos(6)

As you can see only the substitution is performed. To evaluate the result just call evaluate.

              
var e = nerdamer('x^2+2*(cos(x)+x*x)',{x:6}).evaluate();

console.log(e);

//result:
//109.92034057330073
 

Alternatively you can pass an object containing known values into evaluate instead of nerdamer to get back the value right away. The values passed in don't have to be number the can be another expression if needed.

              
var e = nerdamer('x^2+y',{y:'x^2+8'});
console.log(e.text());

//result:
//2*x^2+8

or

              
var x = nerdamer('y^2+1');
var e = nerdamer('4*x+9', {x: x});
console.log(e.text());

//result:
//13+4*y^2

Every time you parse an expression it's stored in nerdamer. To get a list of all the expressions you just call nerdamer.expressions().

              
var knownValues = {x:'x^2+1'};
nerdamer('x^2+2*(cos(x)+x*x)', knownValues );
nerdamer('sin(x)^2+cos(x)^2', knownValues );

console.log(nerdamer.expressions());

//result:
//[ 46.692712758272776, 1 ]

You can request it as an object as well by passing in true. This can be convenient in some situations as the numbering starts at 1;

              
var knownValues = {x:'x^2+1'};
nerdamer('x^2+2*(cos(x)+x*x)', knownValues );
nerdamer('sin(x)^2+cos(x)^2', knownValues );

console.log(nerdamer.expressions(true));

//{ '1': '2*cos(1+x^(2))+3*(1+x^(2))^(2)',
//'2': 'cos(1+x^(2))^(2)+sin(1+x^(2))^(2)' }

Functions aren't always immediately parsed to numbers. For example


var result = nerdamer('cos(x)',{x:6});
console.log(result.text());
//cos(6)

will only subsitute out the variable name. To change this behaviour numer should be passed in as the 3rd argument.


var result = nerdamer('cos(x)',{x:6}, 'numer');
console.log(result.text());
//0.960170286650366

or alternatively


var result = nerdamer('cos(x)',{x:6}).evaluate();
console.log(result.text());
//0.960170286650366

The difference however is that the first option directly substitutes the variables while the second first evaluates the variable and then makes the substitutions. This library utilizes native javascript functions as much as possible. As a result it inherits whatever rounding errors they possess. Take this example for instance.


var result = nerdamer('sqrt(x)*sqrt(x)-2', {x:2});
console.log(result.text());
//4.440892098500626e-16

Yup, it's not zero. To minimize this error it would be better to first simplify the expression and then make your substitutions. The above example would then be      This is no longer the case in this particular example.


var result = nerdamer('sqrt(x)*sqrt(x)-2').evaluate({x:2});
console.log(result.text());
//0
//the expression first becomes x-2 and therefore avoids rounding errors

An expression can be replaced directly by passing in the index of which expression to override. For example


nerdamer('cos(x)',{x:6}, 'numer');
nerdamer('sin(x)+y',{x:6}, null, 1);
console.log(nerdamer.expressions());
//[ 'sin(6)+y' ]

If multiple modifier options need to be passed into nerdamer you can do so using an array. For example, if the Algebra module is loaded you can pass in the expand modifier along with the numer modifier.


var e = nerdamer('cos(x)+(y-x)^2', {x:7}, ['expand', 'numer']);
console.log(e.text());
//-14*y+y^2+49.7539022543433

If you need the code as latex you can pass in true as the second parameter when requesting the expressions.

            
nerdamer('x^2+2*(cos(x)+x*x)');
nerdamer('sin(x)^0.25+cos(x)^0.5' );

console.log(nerdamer.expressions(true, true));

//{ '1': '3~{x}^{2}+2~\\cos\\left(x\\right)',
//'2': '\\sin\\left(x\\right)^{\\frac{1}{4}}+\\sqrt{\\cos\\left(x\\right)}' }

You can specify a particular location when adding an expression, which is specified with the third parameter.


nerdamer('x^2+2*(cos(x)+x*x)');
nerdamer('sin(x)^0.25+cos(x)^0.5' );
nerdamer('expr-override', undefined, 2 );

console.log(nerdamer.expressions(true, true));

//{ '1': '3~{x}^{2}+2~\\cos\\left(x\\right)',
//'2': '-override+expr' 

Here's an example of reserved keywords.


nerdamer.reserved();
//result:
//parens, cos, sin, tan, sec, csc, cot, acos, asin, atan, exp, log, abs, sqrt, diff, 
//integrate, sec, cot, csc, pi, e

//or as an array

nerdamer.reserved(true);
//result:
//[ 'parens','cos','sin','tan','sec','csc','cot','acos','asin','atan','exp','log','abs',
// 'sqrt','diff','integrate','sec','cot','csc','pi','e' ]

A list can and should be generated by calling the reserved method. Most math functions are passed in as part of the expression. If you want to differentiate for instance you just use the function diff which is located in the Calculus module as of 0.5.0

            
var e = nerdamer('diff(x^2+2*(cos(x)+x*x),x)');

console.log(e.text());

//result: 
//-2*sin(x)+6*x

Nerdamer can also handle runtime functions. To do this use the method setFunction. The runtime functions do have symbolic capabilities and support for imaginary numbers. The setfunction method is used as follows: nerdamer.setFunction( function_name, parameter_array, function_body ) For Example:

            
//generate some points
var f = function(x) { return 5*x-1; }
console.log(f(1)); //4
console.log(f(2)); //9 - value to be found
console.log(f(7)); //34

nerdamer.setFunction('interpolate',['y0','x0','y1','x1','x'],'y0+(y1-y0)*((x-x0)/(x1-x0))')
var answer = nerdamer('interpolate(4,1,34,7,2)').evaluate();

console.log(answer);

//result: 9

If you need to add a constant use the setConstant method

            
nerdamer.setConstant( 'g', 9.81);

var weight = nerdamer('100*g').evaluate();

console.log(weight);

//result:
//981

To delete just set it to delete

            
nerdamer.setConstant( 'g', 'delete');

You also have the option of exporting your function to a JavaScript function which can be useful if you need some filtering from user input. Do keep in mind that the parameters are sorted alphabetically for more than one parameter. To use it add the expression to nerdamer and use the buildFunction method.

            
var f = nerdamer('x^2+5').buildFunction();
console.log(f(9));

//result:
//86

If you have a particular order in which you need the parameters to be set, then you pass in an array with the variables in the order in which you want them for instance:

  
var f = nerdamer('z+x^2+y').buildFunction(['y', 'x', 'z']);
console.log(f(9,2,1));
//result
//14

Every time you add an expression to nerdamer it's stored. To list the expressions currently in nerdamer call the 'expressions' method. To delete an expression use the 'clear' method and pass in the expression you want to delete. To clear everything pass in the string 'all'.

            
nerdamer('n*R*T/v');
nerdamer('mc^2');
nerdamer('G*m1*m2/d^2');

nerdamer.clear(2);

console.log(nerdamer.expressions(true));

//result:
//{ '1': 'R*T*n*v^(-1)', '2': 'G*d^(-2)*m1*m2' }

nerdamer.clear('all');
console.log(nerdamer.expressions(true));

//result:
//{}

To get a list of variables call the variables method.

            
var variables = nerdamer('x^2+5*y+bubble_gum').variables();

console.log(variables);
//[ 'bubble_gum', 'x', 'y' ]


Functions, Operations, and Chaining

You can access the built-in functions directly given its name. For example:

 
var ans = nerdamer.tan('pi/4');
console.log(ans.toString()); // 1
Or this if the Calculus module is loaded
 
var ans = nerdamer.diff('log(x)/x', 'x');
console.log(ans.toString()); // -log(x)*x^(-2)+x^(-2)
Or expand your expression
 
var ans = nerdamer.expand('(x+1)^3');
console.log(ans.toString()); // 1+3*x+3*x^2+x^3

You can see the list of built-in functions here Additionally the expressions can be chained

 
var ans = nerdamer('a+b').multiply(2).pow(3);
console.log(ans.toString()); // 8*(a+b)^3
The supported operations are add, subtract, multiply, divide, pow

Solving equations

To solve equations first load Solve.js. Just remember that Solve also required Algebra.js and Calculus.js to be loaded. You can then solve equations using nerdamer. For example:

  
var sol = nerdamer.solveEquations('x^3+8=x^2+6','x');
console.log(sol.toString());
//1+1.000000000000001*i,-1.000000000000001*i+1,-1

Notice that we use toString rather than text as this returns a JavaScript array.
You can also solve an expression


var e = nerdamer.solveEquations('x^2+4-y', 'y');
console.log(e[0].text());
//4+x^2

You can also solve multivariate equations

  
var sol = nerdamer.solveEquations('x^2+8+y=x+6','x');
console.log(sol.toString());
//0.5*((-4*y-7)^0.5+1),0.5*(-(-4*y-7)^0.5+1)

You can do up to 3rd order polynomials for multivariate polynomials.

Additionally you can try for equations containing functions. This is more of a hit or miss approach but it's there if you want to give it a try

var sol = nerdamer.solveEquations('cos(x)+cos(3*x)=1','x');
console.log(sol.toString());
//5.7981235959208695,0.4850617112587174

To solve a system of linear equations pass them in as an array. For example

var sol = nerdamer.solveEquations(['x+y=1', '2*x=6', '4*z+y=6']);
console.log(sol);
//[ [ 'x', 3 ], [ 'y', -2 ], [ 'z', 2 ] ]

In version 0.7.2 and up the solver can additionally be used in the following way

//first parse the equation
var x = nerdamer('x^2+2=y-7*a');
//You can make substitutions to the equation
x = x.evaluate({a: 'x^2-3'});
console.log(x.toString()); //2+x^2=-7*x^2+21+y
var solutions = x.solveFor('x');
console.log(solutions.toString()); //(1/16)*sqrt(32*y+608),(-1/16)*sqrt(32*y+608)  
If no solutions could be found then the array will be empty

Logging Steps

One of the frequently asked questions is how to log the steps of the parsing. To aid in this I've created a helper. The code can be found below or you can find it at this Github gist. This helper creates a function called stepper which can be passed an object containing pre and post functions. For instance to log addition the pre_add and post_add functions get passed to the stepper. The operations which can be logged are called add, subtract, multiply, divide, pow, and call_function. To override an existing entry pass the object along with true to the stepper function. See examples below

Below is the stepper method assuming nerdamer is already loaded in your page or node environment.

var stepper = (function() {
    "use strict";
    var core = nerdamer.getCore(),
        _ = core.PARSER,
        //the container for the function steps
        stepper = {},
        //nerdamer makes recursive calls when adding, subtracting, etc. Making
        //sure the stack is clear ensures that we're at the first call
        stack = [];
    //a function to add calls to the stack
    var wrapper = function(f, a, b) {
        stack.push('lock');
        var r = f(a, b);
        stack.pop();
        return r;
    };
    //This logging function makes sure that there aren't any items on the stack
    //before logging
    var logger = function() { 
        if(stack.length === 0 && typeof this === 'function')
            this.apply(undefined, arguments);
    };
    
    //the semi-globals
    var add, subtract, divide, multiply, pow, fcall;
    
    var load = function() {
        //ADD
        add = _.add;
        var step_add = function(a, b) { 
            var result;
            logger.call(stepper.pre_add, a, b);
            var wrapper_result = wrapper(function(a, b){
                result = add.call(_, a.clone(), b.clone());
                return result;
            }, a, b);
            logger.call(stepper.post_add, result, a, b);
            return wrapper_result;
        };
        _.add = step_add;
        //SUBTRACT
        subtract = _.subtract;
        var step_subtract = function(a, b) { 
            var result;
            logger.call(stepper.pre_subtract, a, b);
            var wrapper_result = wrapper(function(a, b){
                result = subtract.call(_, a.clone(), b.clone());
                return result;
            }, a, b);
            logger.call(stepper.post_subtract, result, a, b);
            return wrapper_result;
        };
        _.subtract = step_subtract;
        //DIVIDE
        divide = _.divide;
        var step_divide = function(a, b) { 
            var result;
            logger.call(stepper.pre_divide, a, b);
            var wrapper_result = wrapper(function(a, b){
                result = divide.call(_, a.clone(), b.clone());
                return result;
            }, a, b);
            logger.call(stepper.post_divide, result, a, b);
            return wrapper_result;
        };
        _.divide = step_divide;
        //MULTIPLY
        multiply = _.multiply;
        var step_multiply = function(a, b) { 
            var result;
            logger.call(stepper.pre_multiply, a, b);
            var wrapper_result = wrapper(function(a, b){
                result = multiply.call(_, a.clone(), b.clone());
                return result;
            }, a, b);
            logger.call(stepper.post_multiply, result, a, b);
            return wrapper_result;
        };
        _.multiply = step_multiply;
        //POW
        pow = _.pow;
        var step_pow = function(a, b) { 
            var result;
            logger.call(stepper.pre_pow, a, b);
            var wrapper_result = wrapper(function(a, b){
                result = pow.call(_, a.clone(), b.clone());
                return result;
            }, a, b);
            logger.call(stepper.post_pow, result, a, b);
            return wrapper_result;
        };
        _.pow = step_pow;
        //CALLFUNCTION
        //function calls are not recursive and can have more than one call on the stack
        //because of this we don't use the wrapper
        fcall = _.callfunction;
        var step_fcall = function(fname, args) {
            if(stepper.pre_function_call && typeof stepper.pre_function_call === 'function')
                stepper.pre_function_call.call(undefined, fname, args);
            var f = fcall.call(_, fname, args);
            if(stepper.post_function_call && typeof stepper.post_function_call === 'function')
                stepper.post_function_call.call(undefined, f, fname, args);
            return f;
        };
        _.callfunction = step_fcall;
    };
    
    load(); //fire away
    
    var xport = function(o, override) {
        for(var x in o) {
            if(!stepper[x] || stepper[x] && override)
                stepper[x] = o[x];
        }
    };
    
    xport.unload = function() {
        _.add = add;
        _.subtract = subtract;
        _.multiply = multiply;
        _.divide = divide;
        _.pow = pow;
        _.callfunction = fcall;
    };
    
    xport.clear = function() {
        stepper = {};
    };
    
    xport.load = load;
    
    return xport;
})();

You can then define your step methods

stepper({
    pre_add: function(a, b) {
        console.log('Adding '+a+' to '+b);
    },
    pre_subtract: function(a, b) {
        console.log('Subtracting '+a+' from '+b);
    },
    pre_multiply: function(a, b) {
        console.log('Multiplying '+a+' by '+b);
    },
    pre_divide: function(a, b) {
        console.log('Dividing '+a+' by '+b);
    },
    pre_pow: function(a, b) {
        console.log('Raising '+a+' to the power of '+b);
    },
    pre_function_call: function(fname, args) {
        console.log('The function '+fname+' was called with arguments '+args);
    },
    post_function_call: function(f) {
        console.log('Afterwards this resulted in '+f+'\n');
    },
    post_add: function(result, a, b) {
        console.log('The result of adding '+a+' to '+b+' was '+result+'\n');
    },
    post_subtract: function(result, a, b) {
        console.log('The result of subtracting '+a+' from '+b+' was '+result+'\n');
    },
    post_multiply: function(result, a, b) {
        console.log('The result of multiplying '+a+' by '+b+' was '+result+'\n');
    },
    post_divide: function(result, a, b) {
        console.log('The result of dividing '+a+' by '+b+' was '+result+'\n');
    },
    post_pow: function(result, a, b) {
        console.log('The result of raising '+a+' to the powe rof '+b+' was '+result+'\n');
    }
});
var x = nerdamer('9/3*2^3-3+1');
console.log('Finally the end result was '+x.toString());

/* OUTPUT: 
Dividing 9 by 3
The result of dividing 9 by 3 was 3

Raising 2 to the power of 3
The result of raising 2 to the power of 3 was 8

Multiplying 3 by 8
The result of multiplying 3 by 8 was 24

Subtracting 24 from 3
The result of subtracting 24 from 3 was 21

Adding 21 to 1
The result of adding 21 to 1 was 22

Finally the end result was 22
*/

If you would want to override the existing pre_add example for instance you can do so in the following manner

stepper({
    pre_add: function() {
        console.log('Overridden');
    }
}, true);

To unload the stepper call the unload method

stepper.unload();

To reload the stepper call the load method

stepper.load();

To clear the stepper call the clear method

stepper.clear();