nerdamer
Version:
javascript light-weight symbolic math expression evaluator
135 lines (121 loc) • 7.39 kB
JavaScript
/* global expect */
;
var utils = require('./support/utils');
var parse = utils.parse;
var _$ = utils.toFixed;
describe('Basic operations', function() {
it('should add correctly', function(){expect(parse('1+1')).toEqual(2);});
it('should subtract correctly', function(){expect(parse('3-1')).toEqual(2);});
it('should divide correctly', function(){expect(parse('6/3')).toEqual(2);});
it('should multiply correctly', function(){expect(parse('2*6')).toEqual(12);});
it('should raise to power correctly', function(){expect(parse('2^3')).toEqual(8);});
it('should parse scientific notation correctly', function(){expect(parse('1.234e+1')).toEqual(12.34);});
it('should parse non-normalized scientific notation correctly', function(){expect(parse('12.3e-1')).toEqual(1.23);});
});
describe('Order of precedence', function() {
it('should recognize * > +', function(){expect(parse('3*5+3')).toEqual(18);});
it('should recognize + = -', function(){expect(parse('4+5-11')).toEqual(-2);});
it('should recognize ^ = +', function(){expect(parse('2^3-3')).toEqual(5);});
it('should recognize ^ > *', function(){expect(parse('2^3*3')).toEqual(24);});
it('should recognize / = *', function(){expect(parse('6/3*5')).toEqual(10);});
it('should recognize / = +', function(){expect(_$(parse('2/3+2/3'))).toEqual(_$(1.3333333333333333));});
it('should recognize ^ is right associative', function(){expect(parse('2^3^2')).toEqual(512);});
});
describe('Percentages', function() {
it('should calculate percentages', function(){expect(parse('5%')).toEqual(0.05);});
it('should add percentages', function(){expect(parse('5%+5%')).toEqual(0.1);});
it('should multiply percentages', function(){expect(parseFloat(parse('10%*10%').toFixed(2))).toEqual(0.01);});
it('should multiply percentages by numbers', function(){expect(parse('100*10%')).toEqual(10);});
});
describe('Functions', function() {
it('should calculate functions', function(){expect(_$(parse('sin(1)'))).toEqual(_$(0.8414709848078965));});
it('should calculate functions', function(){expect(_$(parse('sin(sin(2))'))).toEqual(_$(0.7890723435728884));});
it('should add with functions', function(){expect(_$(parse('sin(sin(2))+4'))).toEqual(_$(4.789072343572888));});
it('should handle function with arguments', function(){expect(parse('max(4,6,3)')).toEqual(6);});
it('should handle function with arguments with operations', function(){expect(parse('max(4,5+7,3)')).toEqual(12);});
it('should handle function with arguments with operations and subsequent operations',
function(){expect(parse('max(4,5+7,3)+11')).toEqual(23);}
);
});
describe('Modulus', function() {
it('should calculate modulus', function(){expect(parse('10%4')).toEqual(2);});
it('should add with modulus', function(){expect(parse('10%4+6')).toEqual(8);});
it('should multiply with modulus', function(){expect(parse('10%4*8')).toEqual(16);});
it('should add and multiply with modulus', function(){expect(parse('2+10%4*8')).toEqual(18);});
it('should respect modulus in functions', function(){expect(parse('max(3,2+10%4*8,5)')).toEqual(18);});
it('should respect modulus with percentages', function(){expect(parse('8000%%8')).toEqual(0);});
it('should correctly handle modulus left assoc', function(){expect(parse('3*3%9')).toEqual(0);});
});
describe('Brackets', function() {
it('should respect parentheses', function(){expect(parse('4*(2+1)')).toEqual(12);});
it('should respect parentheses within parentheses', function(){expect(parse('3*(4+(2+1))')).toEqual(21);});
it('should recognize vectors', function(){expect(parse('[1,2,[3,4]]').toString()).toEqual('[1,2,[3,4]]');});
it('should handle multiple levels of brackets', function() {expect(parse('((((((((9))))))))+1')).toEqual(10);});
it('should handle multiple levels of brackets', function() {expect(parse('((((((1+1))+4)))+3)')).toEqual(9);});
});
describe('Prefixes', function() {
it('should correctly parse prefixes', function(){
expect(parse('-(-3*-(4))')).toEqual(-12);
expect(_$(parse('3^-1^-1'))).toEqual(_$(0.333333333333333));
expect(parse('-(-1-+1)^2')).toEqual(-4);
expect(parse('-(-1-1+1)')).toEqual(1);
expect(parse('-(1)--(1-1--1)')).toEqual(0);
expect(parse('-(-(1))-(--1)')).toEqual(0);
expect(_$(parse('5^-2^-4'))).toEqual(_$(0.9043038394024115));
expect(parse('5^---3')).toEqual(0.008);
expect(parse('5^-(++1+--+2)')).toEqual(0.008);
expect(parse('(5^-(++1+--+2))^-2')).toEqual(15625);
expect(parse('(5^-3^2)')).toEqual(5.12e-7);
expect(parse('-(--5*--7)')).toEqual(-35);
});
});
/*
//Future TODO. The skeleton is there but currently too many specs fail
describe('Spaces', function() {
it('should respect spaces when parsing', function(){
expect(parse('sin 9')).toEqual(0.4121184852417566);
});
it('should ingore other spaces when parsing', function(){
expect(parse('sin 9 + 11')).toEqual(11.4121184852417566);
expect(parse('sin 9+ 11')).toEqual(11.4121184852417566);
expect(parse('sin 9+11')).toEqual(11.4121184852417566);
expect(parse('2* sin 9+11')).toEqual(11.824236970483513);
expect(parse('2 * sin 9+11')).toEqual(11.824236970483513);
expect(parse(' 2 * sin 9+11 ')).toEqual(11.824236970483513);
});
it('should correctly identify spaces with arguments', function(){
expect(parse(' max( 5 , 2 , 17 ) ')).toEqual(17);
});
it('should correctly identify matrices with spaces', function(){
expect(parse('[ 1, [ 3, 5, 7 ] , [1 , [2, [ 1, 2] ]] ]').toString()).toEqual('[1,[3,5,7],[1,[2,[1,2]]]]');
});
});
*/
describe('Accessing vectors', function(){
it('should correctly access vectors', function(){
expect(parse('[1,[3,5,7],[1,[2,[1,2]]]][2]').toString()).toEqual('[1,[2,[1,2]]]');
expect(parse('[1,[3,5,7],[1,[2,[1,2]]]][2][1]').toString()).toEqual('[2,[1,2]]');
expect(parse('[1,[3,5,7],[1,[2,[1,2]]]][2][1][1]').toString()).toEqual('[1,2]');
expect(parse('[1,[3,5,7],[1,[2,[1,2]]]][2][1][1][0]').toString()).toEqual('1');
expect(parse('5*[1,[3,5,7],[1,[2,[1,2]]]][2][1][1][0]').toString()).toEqual('5');
expect(parse('5*[1,[3,5,7],[1,[2,[1,2]]]][2][1][1][0]+8').toString()).toEqual('13');
});
it('should access ranges', function(){
expect(parse('[1,2,3,4,5][1:4]').toString()).toEqual('[2,3,4]');
});
it('should access using negative indices', function(){
expect(parse('[1,2,3,4,5][-2]').toString()).toEqual('4');
});
it('should not confuse vector wit accessor', function(){
expect(parse('[[1,2],[3,4],[5,6]]').toString()).toEqual('[[1,2],[3,4],[5,6]]');
});
});
describe('Setting vector values', function() {
it('should set values of vectors with the assign operator', function() {
expect(parse('[1,2][1]:x').toString()).toEqual('[1,x]');
});
});
describe('Substitutions', function(){
it('should substitute x', function() {expect(parse('x+1', {x: 4})).toEqual(5);});
it('should substitute x', function() {expect(parse('2*x+1', {x: 4})).toEqual(9);});
});