Added Sigma operator – support for more complex operators 🌟
Fix README.md links pointing to Equation.js instead of Equation Bump version to 1.3.0
This commit is contained in:
parent
6a5120ec22
commit
485ebb3c9d
11
README.md
11
README.md
@ -1,8 +1,8 @@
|
|||||||
Equation [![Build Status](https://travis-ci.org/mdibaiee/Equation.js.svg?branch=master)](https://travis-ci.org/mdibaiee/Equation.js)
|
Equation [![Build Status](https://travis-ci.org/mdibaiee/Equation.svg?branch=master)](https://travis-ci.org/mdibaiee/Equation.js)
|
||||||
========
|
========
|
||||||
Solve math expressions or create equations for repeated and complex Math tasks.
|
Solve math expressions or create equations for repeated and complex Math tasks.
|
||||||
|
|
||||||
To use in browser, download [`equation.min.js`](https://raw.githubusercontent.com/mdibaiee/Equation.js/master/equation.min.js).
|
To use in browser, download [`equation.min.js`](https://raw.githubusercontent.com/mdibaiee/Equation/master/equation.min.js).
|
||||||
|
|
||||||
Install using npm:
|
Install using npm:
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ console.log(test(4, 3)).to.equal(8 + 18);
|
|||||||
You can also register your own operators and constants.
|
You can also register your own operators and constants.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// these options are explained below
|
// these options are explained in [`operators.js`](https://github.com/mdibaiee/Equation/blob/master/lib/operators.js).
|
||||||
Equation.registerOperator('$', {
|
Equation.registerOperator('$', {
|
||||||
fn: a => 1/a,
|
fn: a => 1/a,
|
||||||
format: '10',
|
format: '10',
|
||||||
@ -42,9 +42,12 @@ Equation.registerConstant('N', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Equation.solve('N'); // a number between 10 and 20
|
Equation.solve('N'); // a number between 10 and 20
|
||||||
|
|
||||||
|
// Complex operators
|
||||||
|
Equation.solve('sigma(0, 5, 2@ + 5)'); // 60
|
||||||
```
|
```
|
||||||
|
|
||||||
For a list of operators and constants see [`operators.js`](https://github.com/mdibaiee/Equation.js/blob/master/lib/operators.js) and [`constants.js`](https://github.com/mdibaiee/Equation.js/blob/master/lib/constants.js).
|
For a list of operators and constants see [`operators.js`](https://github.com/mdibaiee/Equation/blob/master/lib/operators.js) and [`constants.js`](https://github.com/mdibaiee/Equation/blob/master/lib/constants.js).
|
||||||
|
|
||||||
API
|
API
|
||||||
===
|
===
|
||||||
|
33
dist/index.js
vendored
33
dist/index.js
vendored
@ -107,6 +107,13 @@ var Equation = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 2x + 5x * x => 7x^2
|
||||||
|
simplify: function simplify(expression) {
|
||||||
|
var stack = parseExpression(expression);
|
||||||
|
|
||||||
|
console.log(stack);
|
||||||
|
},
|
||||||
|
|
||||||
registerOperator: function registerOperator(key, options) {
|
registerOperator: function registerOperator(key, options) {
|
||||||
_operators2['default'][key] = options;
|
_operators2['default'][key] = options;
|
||||||
},
|
},
|
||||||
@ -127,7 +134,13 @@ var solveStack = (function (_solveStack) {
|
|||||||
|
|
||||||
return solveStack;
|
return solveStack;
|
||||||
})(function (stack) {
|
})(function (stack) {
|
||||||
if (stack.some(Array.isArray)) {
|
// if an operator takes an expression argument, we should not dive into it
|
||||||
|
// and solve the expression inside
|
||||||
|
var hasExpressionArgument = stack.some(function (a) {
|
||||||
|
return _operators2['default'][a] && _operators2['default'][a].hasExpression;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasExpressionArgument && stack.some(Array.isArray)) {
|
||||||
stack = stack.map(function (group) {
|
stack = stack.map(function (group) {
|
||||||
if (!Array.isArray(group)) {
|
if (!Array.isArray(group)) {
|
||||||
return group;
|
return group;
|
||||||
@ -159,6 +172,12 @@ var MIN_PRECEDENCE = Math.min.apply(Math, _toConsumableArray(PRECEDENCES));
|
|||||||
* The parsed array
|
* The parsed array
|
||||||
*/
|
*/
|
||||||
var parseExpression = function parseExpression(expression) {
|
var parseExpression = function parseExpression(expression) {
|
||||||
|
// function arguments can be separated using comma,
|
||||||
|
// but we parse as groups, so this is the solution to getting comma to work
|
||||||
|
// sigma(0, 4, 2@) becomes sigma(0)(4)(2@) so every argument is parsed
|
||||||
|
// separately
|
||||||
|
expression = expression.replace(/,/g, ')(');
|
||||||
|
|
||||||
var stream = new _ReadStream2['default'](expression),
|
var stream = new _ReadStream2['default'](expression),
|
||||||
stack = [],
|
stack = [],
|
||||||
record = '',
|
record = '',
|
||||||
@ -238,19 +257,19 @@ var parseExpression = function parseExpression(expression) {
|
|||||||
*/
|
*/
|
||||||
var parseGroups = function parseGroups(stack) {
|
var parseGroups = function parseGroups(stack) {
|
||||||
// Parantheses become inner arrays which will then be processed first
|
// Parantheses become inner arrays which will then be processed first
|
||||||
var sub = 0;
|
var depth = 0;
|
||||||
return stack.reduce(function (a, b) {
|
return stack.reduce(function (a, b) {
|
||||||
if (b.indexOf('(') > -1) {
|
if (b.indexOf('(') > -1) {
|
||||||
if (b.length > 1) {
|
if (b.length > 1) {
|
||||||
_.dive(a, sub).push(b.replace('(', ''), []);
|
_.dive(a, depth).push(b.replace('(', ''), []);
|
||||||
} else {
|
} else {
|
||||||
_.dive(a, sub).push([]);
|
_.dive(a, depth).push([]);
|
||||||
}
|
}
|
||||||
sub++;
|
depth++;
|
||||||
} else if (b === ')') {
|
} else if (b === ')') {
|
||||||
sub--;
|
depth--;
|
||||||
} else {
|
} else {
|
||||||
_.dive(a, sub).push(b);
|
_.dive(a, depth).push(b);
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}, []);
|
}, []);
|
||||||
|
29
dist/operators.js
vendored
29
dist/operators.js
vendored
@ -1,8 +1,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
|
||||||
|
|
||||||
Object.defineProperty(exports, '__esModule', {
|
Object.defineProperty(exports, '__esModule', {
|
||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var _Equation = require('equation');
|
||||||
|
|
||||||
|
var _Equation2 = _interopRequireWildcard(_Equation);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Operators and Functions
|
* Operators and Functions
|
||||||
* fn: function used to evaluate value
|
* fn: function used to evaluate value
|
||||||
@ -11,6 +18,11 @@ Object.defineProperty(exports, '__esModule', {
|
|||||||
* e.g: factorial is 01, add is 010, like 2!, 2+2
|
* e.g: factorial is 01, add is 010, like 2!, 2+2
|
||||||
* precedence: determines which operators should be evaluated first
|
* precedence: determines which operators should be evaluated first
|
||||||
* the lower the value, the higher the precedence
|
* the lower the value, the higher the precedence
|
||||||
|
* hasExpression: determines if any of the operator arguments are an expression
|
||||||
|
* This way, arguments will not be solved by equation and instead
|
||||||
|
* you have to call solve on each argument yourself.
|
||||||
|
* You get the arguments as parsed arrays sigma(0, 5, 2@) becomes
|
||||||
|
* sigma(0, 5, [2, '*', '@']). See sigma operator for reference
|
||||||
*/
|
*/
|
||||||
exports['default'] = {
|
exports['default'] = {
|
||||||
'^': {
|
'^': {
|
||||||
@ -119,6 +131,23 @@ exports['default'] = {
|
|||||||
fn: Math.floor,
|
fn: Math.floor,
|
||||||
format: '10',
|
format: '10',
|
||||||
precedence: -1
|
precedence: -1
|
||||||
|
},
|
||||||
|
sigma: {
|
||||||
|
fn: function fn(from, to, expression) {
|
||||||
|
var expr = expression.join('').replace(/,/g, '');
|
||||||
|
var regex = new RegExp(ITERATOR_SIGN, 'g');
|
||||||
|
|
||||||
|
var sum = 0;
|
||||||
|
for (var i = from; i <= to; i++) {
|
||||||
|
sum += _Equation2['default'].solve(expr.replace(regex, i));
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
},
|
||||||
|
format: '1000',
|
||||||
|
hasExpression: true,
|
||||||
|
precedence: -1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var ITERATOR_SIGN = '@';
|
||||||
module.exports = exports['default'];
|
module.exports = exports['default'];
|
20
dist/tests/solve.js
vendored
20
dist/tests/solve.js
vendored
@ -92,7 +92,25 @@ describe('Constats', function () {
|
|||||||
_expect.expect(_M2['default'].solve('sin(PI/2)')).to.equal(1);
|
_expect.expect(_M2['default'].solve('sin(PI/2)')).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for functions as constants', function () {
|
it('should work for functions as constants - retry on fail', function () {
|
||||||
_expect.expect(_M2['default'].solve('RAND')).to.not.equal(_M2['default'].solve('RAND'));
|
_expect.expect(_M2['default'].solve('RAND')).to.not.equal(_M2['default'].solve('RAND'));
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Sigma', function () {
|
||||||
|
it('should work with simple expressions', function () {
|
||||||
|
_expect.expect(_M2['default'].solve('sigma(0, 5, @)')).to.equal(15);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with more complex expressions', function () {
|
||||||
|
_expect.expect(_M2['default'].solve('sigma(0, 2, 2@+5)')).to.equal(21);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work without an iterator sign', function () {
|
||||||
|
_expect.expect(_M2['default'].solve('sigma(0, 2, 5*2)')).to.equal(30);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with negative start / end points', function () {
|
||||||
|
_expect.expect(_M2['default'].solve('sigma(-5, -2, @)')).to.equal(-14);
|
||||||
|
});
|
||||||
});
|
});
|
76
equation.js
76
equation.js
@ -284,6 +284,13 @@ var Equation = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 2x + 5x * x => 7x^2
|
||||||
|
simplify: function simplify(expression) {
|
||||||
|
var stack = parseExpression(expression);
|
||||||
|
|
||||||
|
console.log(stack);
|
||||||
|
},
|
||||||
|
|
||||||
registerOperator: function registerOperator(key, options) {
|
registerOperator: function registerOperator(key, options) {
|
||||||
_operators2['default'][key] = options;
|
_operators2['default'][key] = options;
|
||||||
},
|
},
|
||||||
@ -304,7 +311,13 @@ var solveStack = (function (_solveStack) {
|
|||||||
|
|
||||||
return solveStack;
|
return solveStack;
|
||||||
})(function (stack) {
|
})(function (stack) {
|
||||||
if (stack.some(Array.isArray)) {
|
// if an operator takes an expression argument, we should not dive into it
|
||||||
|
// and solve the expression inside
|
||||||
|
var hasExpressionArgument = stack.some(function (a) {
|
||||||
|
return _operators2['default'][a] && _operators2['default'][a].hasExpression;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasExpressionArgument && stack.some(Array.isArray)) {
|
||||||
stack = stack.map(function (group) {
|
stack = stack.map(function (group) {
|
||||||
if (!Array.isArray(group)) {
|
if (!Array.isArray(group)) {
|
||||||
return group;
|
return group;
|
||||||
@ -336,6 +349,12 @@ var MIN_PRECEDENCE = Math.min.apply(Math, _toConsumableArray(PRECEDENCES));
|
|||||||
* The parsed array
|
* The parsed array
|
||||||
*/
|
*/
|
||||||
var parseExpression = function parseExpression(expression) {
|
var parseExpression = function parseExpression(expression) {
|
||||||
|
// function arguments can be separated using comma,
|
||||||
|
// but we parse as groups, so this is the solution to getting comma to work
|
||||||
|
// sigma(0, 4, 2@) becomes sigma(0)(4)(2@) so every argument is parsed
|
||||||
|
// separately
|
||||||
|
expression = expression.replace(/,/g, ')(');
|
||||||
|
|
||||||
var stream = new _ReadStream2['default'](expression),
|
var stream = new _ReadStream2['default'](expression),
|
||||||
stack = [],
|
stack = [],
|
||||||
record = '',
|
record = '',
|
||||||
@ -415,19 +434,19 @@ var parseExpression = function parseExpression(expression) {
|
|||||||
*/
|
*/
|
||||||
var parseGroups = function parseGroups(stack) {
|
var parseGroups = function parseGroups(stack) {
|
||||||
// Parantheses become inner arrays which will then be processed first
|
// Parantheses become inner arrays which will then be processed first
|
||||||
var sub = 0;
|
var depth = 0;
|
||||||
return stack.reduce(function (a, b) {
|
return stack.reduce(function (a, b) {
|
||||||
if (b.indexOf('(') > -1) {
|
if (b.indexOf('(') > -1) {
|
||||||
if (b.length > 1) {
|
if (b.length > 1) {
|
||||||
_.dive(a, sub).push(b.replace('(', ''), []);
|
_.dive(a, depth).push(b.replace('(', ''), []);
|
||||||
} else {
|
} else {
|
||||||
_.dive(a, sub).push([]);
|
_.dive(a, depth).push([]);
|
||||||
}
|
}
|
||||||
sub++;
|
depth++;
|
||||||
} else if (b === ')') {
|
} else if (b === ')') {
|
||||||
sub--;
|
depth--;
|
||||||
} else {
|
} else {
|
||||||
_.dive(a, sub).push(b);
|
_.dive(a, depth).push(b);
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}, []);
|
}, []);
|
||||||
@ -650,9 +669,16 @@ exports['default'] = Equation;
|
|||||||
},{"./constants":1,"./helpers":2,"./operators":4,"./readstream":5}],4:[function(require,module,exports){
|
},{"./constants":1,"./helpers":2,"./operators":4,"./readstream":5}],4:[function(require,module,exports){
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
|
||||||
|
|
||||||
Object.defineProperty(exports, '__esModule', {
|
Object.defineProperty(exports, '__esModule', {
|
||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var _Equation = require('equation');
|
||||||
|
|
||||||
|
var _Equation2 = _interopRequireWildcard(_Equation);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Operators and Functions
|
* Operators and Functions
|
||||||
* fn: function used to evaluate value
|
* fn: function used to evaluate value
|
||||||
@ -661,6 +687,11 @@ Object.defineProperty(exports, '__esModule', {
|
|||||||
* e.g: factorial is 01, add is 010, like 2!, 2+2
|
* e.g: factorial is 01, add is 010, like 2!, 2+2
|
||||||
* precedence: determines which operators should be evaluated first
|
* precedence: determines which operators should be evaluated first
|
||||||
* the lower the value, the higher the precedence
|
* the lower the value, the higher the precedence
|
||||||
|
* hasExpression: determines if any of the operator arguments are an expression
|
||||||
|
* This way, arguments will not be solved by equation and instead
|
||||||
|
* you have to call solve on each argument yourself.
|
||||||
|
* You get the arguments as parsed arrays sigma(0, 5, 2@) becomes
|
||||||
|
* sigma(0, 5, [2, '*', '@']). See sigma operator for reference
|
||||||
*/
|
*/
|
||||||
exports['default'] = {
|
exports['default'] = {
|
||||||
'^': {
|
'^': {
|
||||||
@ -769,10 +800,27 @@ exports['default'] = {
|
|||||||
fn: Math.floor,
|
fn: Math.floor,
|
||||||
format: '10',
|
format: '10',
|
||||||
precedence: -1
|
precedence: -1
|
||||||
|
},
|
||||||
|
sigma: {
|
||||||
|
fn: function fn(from, to, expression) {
|
||||||
|
var expr = expression.join('').replace(/,/g, '');
|
||||||
|
var regex = new RegExp(ITERATOR_SIGN, 'g');
|
||||||
|
|
||||||
|
var sum = 0;
|
||||||
|
for (var i = from; i <= to; i++) {
|
||||||
|
sum += _Equation2['default'].solve(expr.replace(regex, i));
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
},
|
||||||
|
format: '1000',
|
||||||
|
hasExpression: true,
|
||||||
|
precedence: -1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var ITERATOR_SIGN = '@';
|
||||||
module.exports = exports['default'];
|
module.exports = exports['default'];
|
||||||
},{}],5:[function(require,module,exports){
|
},{"equation":8}],5:[function(require,module,exports){
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Object.defineProperty(exports, '__esModule', {
|
Object.defineProperty(exports, '__esModule', {
|
||||||
@ -835,5 +883,15 @@ exports['default'] = function (string) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = exports['default'];
|
module.exports = exports['default'];
|
||||||
},{}]},{},[3])(3)
|
},{}],6:[function(require,module,exports){
|
||||||
|
arguments[4][1][0].apply(exports,arguments)
|
||||||
|
},{"dup":1}],7:[function(require,module,exports){
|
||||||
|
arguments[4][2][0].apply(exports,arguments)
|
||||||
|
},{"dup":2}],8:[function(require,module,exports){
|
||||||
|
arguments[4][3][0].apply(exports,arguments)
|
||||||
|
},{"./constants":6,"./helpers":7,"./operators":9,"./readstream":10,"dup":3}],9:[function(require,module,exports){
|
||||||
|
arguments[4][4][0].apply(exports,arguments)
|
||||||
|
},{"dup":4,"equation":8}],10:[function(require,module,exports){
|
||||||
|
arguments[4][5][0].apply(exports,arguments)
|
||||||
|
},{"dup":5}]},{},[3])(3)
|
||||||
});
|
});
|
2
equation.min.js
vendored
2
equation.min.js
vendored
File diff suppressed because one or more lines are too long
33
lib/index.js
33
lib/index.js
@ -80,6 +80,13 @@ let Equation = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 2x + 5x * x => 7x^2
|
||||||
|
simplify(expression) {
|
||||||
|
let stack = parseExpression(expression);
|
||||||
|
|
||||||
|
console.log(stack);
|
||||||
|
},
|
||||||
|
|
||||||
registerOperator(key, options) {
|
registerOperator(key, options) {
|
||||||
operators[key] = options;
|
operators[key] = options;
|
||||||
},
|
},
|
||||||
@ -90,7 +97,13 @@ let Equation = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const solveStack = stack => {
|
const solveStack = stack => {
|
||||||
if (stack.some(Array.isArray)) {
|
// if an operator takes an expression argument, we should not dive into it
|
||||||
|
// and solve the expression inside
|
||||||
|
const hasExpressionArgument = stack.some(a => {
|
||||||
|
return operators[a] && operators[a].hasExpression;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasExpressionArgument && stack.some(Array.isArray)) {
|
||||||
stack = stack.map(group => {
|
stack = stack.map(group => {
|
||||||
if (!Array.isArray(group)) {
|
if (!Array.isArray(group)) {
|
||||||
return group;
|
return group;
|
||||||
@ -122,6 +135,12 @@ const MIN_PRECEDENCE = Math.min(...PRECEDENCES);
|
|||||||
* The parsed array
|
* The parsed array
|
||||||
*/
|
*/
|
||||||
const parseExpression = expression => {
|
const parseExpression = expression => {
|
||||||
|
// function arguments can be separated using comma,
|
||||||
|
// but we parse as groups, so this is the solution to getting comma to work
|
||||||
|
// sigma(0, 4, 2@) becomes sigma(0)(4)(2@) so every argument is parsed
|
||||||
|
// separately
|
||||||
|
expression = expression.replace(/,/g, ')(');
|
||||||
|
|
||||||
let stream = new ReadStream(expression),
|
let stream = new ReadStream(expression),
|
||||||
stack = [],
|
stack = [],
|
||||||
record = '',
|
record = '',
|
||||||
@ -202,19 +221,19 @@ const parseExpression = expression => {
|
|||||||
*/
|
*/
|
||||||
const parseGroups = stack => {
|
const parseGroups = stack => {
|
||||||
// Parantheses become inner arrays which will then be processed first
|
// Parantheses become inner arrays which will then be processed first
|
||||||
let sub = 0;
|
let depth = 0;
|
||||||
return stack.reduce((a, b) => {
|
return stack.reduce((a, b) => {
|
||||||
if (b.indexOf('(') > -1) {
|
if (b.indexOf('(') > -1) {
|
||||||
if (b.length > 1) {
|
if (b.length > 1) {
|
||||||
_.dive(a, sub).push(b.replace('(', ''), []);
|
_.dive(a, depth).push(b.replace('(', ''), []);
|
||||||
} else {
|
} else {
|
||||||
_.dive(a, sub).push([]);
|
_.dive(a, depth).push([]);
|
||||||
}
|
}
|
||||||
sub++;
|
depth++;
|
||||||
} else if (b === ')') {
|
} else if (b === ')') {
|
||||||
sub--;
|
depth--;
|
||||||
} else {
|
} else {
|
||||||
_.dive(a, sub).push(b);
|
_.dive(a, depth).push(b);
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import Equation from 'equation';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Operators and Functions
|
* Operators and Functions
|
||||||
* fn: function used to evaluate value
|
* fn: function used to evaluate value
|
||||||
@ -6,6 +8,11 @@
|
|||||||
* e.g: factorial is 01, add is 010, like 2!, 2+2
|
* e.g: factorial is 01, add is 010, like 2!, 2+2
|
||||||
* precedence: determines which operators should be evaluated first
|
* precedence: determines which operators should be evaluated first
|
||||||
* the lower the value, the higher the precedence
|
* the lower the value, the higher the precedence
|
||||||
|
* hasExpression: determines if any of the operator arguments are an expression
|
||||||
|
* This way, arguments will not be solved by equation and instead
|
||||||
|
* you have to call solve on each argument yourself.
|
||||||
|
* You get the arguments as parsed arrays sigma(0, 5, 2@) becomes
|
||||||
|
* sigma(0, 5, [2, '*', '@']). See sigma operator for reference
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
'^': {
|
'^': {
|
||||||
@ -98,5 +105,22 @@ export default {
|
|||||||
fn: Math.floor,
|
fn: Math.floor,
|
||||||
format: '10',
|
format: '10',
|
||||||
precedence: -1
|
precedence: -1
|
||||||
|
},
|
||||||
|
'sigma': {
|
||||||
|
fn(from, to, expression) {
|
||||||
|
const expr = expression.join('').replace(/,/g, '');
|
||||||
|
const regex = new RegExp(ITERATOR_SIGN, 'g');
|
||||||
|
|
||||||
|
let sum = 0;
|
||||||
|
for (let i = from; i <= to; i++) {
|
||||||
|
sum += Equation.solve(expr.replace(regex, i));
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
},
|
||||||
|
format: '1000',
|
||||||
|
hasExpression: true,
|
||||||
|
precedence: -1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ITERATOR_SIGN = '@';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "equations",
|
"name": "equations",
|
||||||
"version": "1.2.1",
|
"version": "1.3.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
@ -85,7 +85,25 @@ describe('Constats', () => {
|
|||||||
expect(M.solve('sin(PI/2)')).to.equal(1);
|
expect(M.solve('sin(PI/2)')).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for functions as constants', () => {
|
it('should work for functions as constants - retry on fail', () => {
|
||||||
expect(M.solve('RAND')).to.not.equal(M.solve('RAND'));
|
expect(M.solve('RAND')).to.not.equal(M.solve('RAND'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Sigma', () => {
|
||||||
|
it('should work with simple expressions', () => {
|
||||||
|
expect(M.solve('sigma(0, 5, @)')).to.equal(15);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with more complex expressions', () => {
|
||||||
|
expect(M.solve('sigma(0, 2, 2@+5)')).to.equal(21);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work without an iterator sign', () => {
|
||||||
|
expect(M.solve('sigma(0, 2, 5*2)')).to.equal(30);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with negative start / end points', () => {
|
||||||
|
expect(M.solve('sigma(-5, -2, @)')).to.equal(-14);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user