Socket
Socket
Sign inDemoInstall

bigeval

Package Overview
Dependencies
0
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.1 to 2.0.0

309

BigEval.js

@@ -12,3 +12,3 @@ /*

this.errMS = "MISSING_OPERATOR_AT_";
this.errMN = "MISSING_OPERAND_AT_";
this.errMN = "MISSING_OPERAND";
this.errIC = "INVALID_CHAR_AT_";

@@ -19,5 +19,21 @@ this.errFN = "INVALID_FUNCTION_";

this.order = ['!' , '@' , '\\/*%' , '+-' , '&' , '^' , '|'];
// https://en.wikipedia.org/wiki/Order_of_operations#Programming_languages
this.order = [
['!'],
['**'],
['\\', '/', '*', '%'],
['+', '-'],
['<<', '>>'],
['<', '<=', '>', '>='],
['==', '=', '!='],
['&'], ['^'], ['|'],
['&&'], ['||']
];
this.flatOps = [];
for (var i = 0; i < this.order.length; i++) {
this.flatOps = this.flatOps.concat(this.order[i]);
}
// CONSTANTS

@@ -30,4 +46,6 @@ var a = this.CONSTANT = {};

a.E = Math.E;
a.INFINITY = "Infinity";
a.NaN = "NaN";
a.Infinity = Infinity;
a.NaN = NaN;
a.true = true;
a.false = false;
};

@@ -40,12 +58,4 @@

// validate brackets
this.validate(s);
if (this.err)
return this.errMsg;
// replace ** by @
s = s.replace(/\*\*/g, '@');
// validate missing operator
var misOperator = /[a-z0-9][ \t]+[a-z0-9\.]/ig, p;
var misOperator = /[a-z0-9][\s\uFEFF\xA0]+[a-z0-9\.]/ig;
if (misOperator.exec(s)){

@@ -56,14 +66,11 @@ this.err = 1;

// validate missing operand
var misOperands = /[\+\-\\\/\*\@\%\&\^\|][ \t]*([\\\/\*\@\!\%\&\^\|\)]|$)/g;
if (misOperands.exec(s)){
this.err = 1;
return this.errMsg = this.errMN + misOperands.lastIndex;
}
s = this.plusMinus( s.replace(/[ \t]/g, '') );
// validate brackets
this.validate(s);
if (this.err)
return this.errMsg;
s = this.plusMinus( s.replace(/[\s\uFEFF\xA0]/g, '') );
s = this.solve(s);
if (s.charAt(0) == '+')
s = s.slice(1);
return s;

@@ -84,12 +91,13 @@ };

var ob = s.indexOf('('), cb, fname, freturn;
var i;
// if bracket present, work on them
while (ob != -1){
while (ob !== -1){
var obct = 1;
for (var i = ob+1; i < s.length; i++){
for (i = ob+1; i < s.length; i++){
if (s[i] == '(')
obct++;
else if (s[i] == ')'){
else if (s[i] === ')'){
obct--;
if (obct == 0){
if (obct === 0){
cb = i;

@@ -116,11 +124,11 @@ break;

// check for comma - then function throw it back
if (s.indexOf(',') != -1)
if (s.indexOf(',') !== -1)
return this.addPlusSign(s);
// solve expression (no brackets exist)
var p, bp, ap, seg, c, cs, isAddOn=0, b, a;
for (var i = 0; i < this.order.length; i++){
var p, bp, ap, seg, cs, isAddOn=0, b, a, op;
for (i = 0; i < this.order.length; i++){
cs = this.order[i];
if (cs == '+-'){ // resolve +- made due to bracket solving
if (cs[0] === '+'){ // resolve +- made due to bracket solving
s = this.plusMinus(s);

@@ -131,7 +139,9 @@ isAddOn = 1;

p = this.leastIndexOf(s, cs, 1);
op = p[1];
p = p[0];
while (p > 0){ // the first is sign, no need to take that
bp = s.slice(0,p).match(/[\-\+]*(\de\-|\de\+|[a-z0-9_\.])+$/i); // kepp e-,e+ before other regex to have it matched
bp = s.slice(0,p).match(/[\-\+]*(\de\-|\de\+|[a-z0-9_\.])+$/i); // keep e-,e+ before other regex to have it matched
// & ^ | are after + in priority so they dont need be above
ap = s.slice(p+1).match(/[\-\+]*(\de\-|\de\+|[a-z0-9_\.])+/i);
ap = s.slice(p+op.length).match(/[\-\+]*(\de\-|\de\+|[a-z0-9_\.])+/i);
if (ap == null)

@@ -141,3 +151,5 @@ ap = [""];

if (bp == null){ // 12 & -20 - here -20 is sign.. bp of it is null . ignore it
p = this.leastIndexOf(s, cs, p+1);
p = this.leastIndexOf(s, cs, p+op.length);
op = p[1];
p = p[0];
continue;

@@ -152,14 +164,22 @@ }

if ( bp[0].charAt(bp[0].length - 2).match(/\d/) ){ // is number
p = this.leastIndexOf(s, cs, p+1);
p = this.leastIndexOf(s, cs, p+op.length);
op = p[1];
p = p[0];
continue;
}
// look for variables
c = s.charAt(p);
//alert(bp[0] + s.charAt(p) + ap[0]);
b = this.parseVar( this.plusMinus(bp[0]) ); a = this.parseVar( this.plusMinus(ap[0]) );
b = this.plusMinus(bp[0]);
a = this.plusMinus(ap[0]);
if (b === '' || a === '') {
return this.makeError(this.errMN);
}
b = this.parseVar(b);
a = this.parseVar(a);
if (this.err)
return this.errMsg;
if (c == '!'){
if (op == '!'){
if ( bp[0].charAt(0) == '+' || bp[0].charAt(0) == '-' )

@@ -171,26 +191,47 @@ bp[0] = bp[0].slice(1);

} else {
if (c == '/' || c == '\\')
if (op === '/' || op === '\\')
seg = this.div( b , a );
else if (c == '*')
else if (op === '*')
seg = this.mul( b , a );
else if (c == '+')
else if (op === '+')
seg = this.add( b , a );
else if (c == '-')
else if (op === '-')
seg = this.sub( b , a );
else if (c == '@')
else if (op === '<<')
seg = this.shiftLeft( b , a );
else if (op === '>>')
seg = this.shiftRight( b , a );
else if (op === '<')
seg = this.lessThan( b , a );
else if (op === '<=')
seg = this.lessThanOrEqualsTo( b , a );
else if (op === '>')
seg = this.greaterThan( b , a );
else if (op === '>=')
seg = this.greaterThanOrEqualsTo( b , a );
else if (op === '==' || op === '=')
seg = this.equalsTo( b , a );
else if (op === '!=')
seg = this.notEqualsTo( b , a );
else if (op === '**')
seg = this.pow( b , a );
else if (c == '%')
else if (op === '%')
seg = this.mod( b , a );
else if (c == '&')
else if (op === '&')
seg = this.and( b , a );
else if (c == '^')
else if (op === '^')
seg = this.xor( b , a );
else if (c == '|')
seg = this.or( b , a );
else if (op === '|')
seg = this.or( b , a );
else if (op === '&&')
seg = this.logicalAnd( b , a );
else if (op === '||')
seg = this.logicalOr( b , a );
seg = this.addPlusSign(seg + "");
}
s = s.slice(0, p-bp[0].length) + seg + s.slice(p+ap[0].length+1);
p = this.leastIndexOf(s, cs, 1);
//alert(s);
s = s.slice(0, p-bp[0].length) + seg + s.slice(p+ap[0].length+op.length);
p = this.leastIndexOf(s, cs, 1);
op = p[1];
p = p[0];
}

@@ -200,3 +241,3 @@ }

s = this.addPlusSign(s);
return this.parseVar(s);
return s === '' ? NaN : this.parseVar(s);
};

@@ -206,3 +247,3 @@

// checks expression for errors
var stack = [], err = 0;
var stack = [];

@@ -260,32 +301,80 @@ for ( var i = 0; i < s.length; i++ ){

var z;
//console.log(s);
if (z = s.match(/^[\+\-]?[a-z][a-z0-9_]*$/i)){
var zs="";
if (z[0].charAt(0) == '-' || z[0].charAt(0) == '+'){
zs = z[0].slice(0,1);
if (z = s.match(/^[\+\-]?[a-z][a-z0-9_]*$/i)) {
var sign = false;
if (z[0][0] == '-' || z[0][0] == '+'){
sign = z[0][0] === '-';
z[0] = z[0].slice(1);
}
var c;
if (typeof this.CONSTANT[z[0].toUpperCase()] !== 'undefined')
return zs + this.CONSTANT[ z[0].toUpperCase() ];
c = this.CONSTANT[z[0].toUpperCase()];
else if (typeof this.CONSTANT[z[0]] !== 'undefined')
return zs + this.CONSTANT[ z[0] ];
c = this.CONSTANT[z[0]];
else
return this.makeError(this.errVD + z[0]);
if (typeof c === 'boolean')
return c;
// Safeguard to always work with numbers
c = this.number((typeof c === 'string' && c[0] === '+') ? c.substr(1) : c);
return sign ? -c : c;
}
else
return s;
return this.number((typeof s === 'string' && s[0] === '+') ? s.substr(1) : s);
};
BigEval.prototype.opAtPosition = function(s, p) {
var op = '';
for (var j = 0, jlen = this.flatOps.length; j < jlen; j++) {
var item = this.flatOps[j];
if (op === item || item.length <= op.length)
continue;
if (s.substr(p, item.length) === item) {
op = item;
}
}
return op;
};
BigEval.prototype.leastIndexOf = function(s, cs, sp){
var l = -1, p;
for (var i=0; i<cs.length; i++){
p = s.indexOf(cs[i], sp);
if (p==-1)
var l = -1, p, m, item, j, jlen = this.flatOps.length, op;
for (var i = 0; i < cs.length; i++){
item = cs[i];
p = s.indexOf(item, sp);
// If it's the wrong op because it's shorter, look further
while (p !== -1 && (op = this.opAtPosition(s, p)) !== item) {
p = s.indexOf(item, p + op.length);
}
if (p == -1)
continue;
if (l==-1)
l=p;
else if (p<l)
l=p;
// Avoid taking partial op when longer ops are available
for (j = 0; j < jlen; j++) {
jop = this.flatOps[j];
if (jop === item || jop.length <= item.length) continue;
if (s.substr(p, jop.length) === jop) {
p = -1;
break;
}
}
if (l == -1 || p < l) {
l = p;
m = item;
}
}
return l;
return [l, m];
};

@@ -308,3 +397,2 @@

/**

@@ -314,25 +402,60 @@ * Extension functions

BigEval.prototype.number = function(str){
return Number(str);
};
BigEval.prototype.add = function(a, b){
return Number(a)+Number(b);
return a + b;
};
BigEval.prototype.sub = function(a, b){
return Number(a)-Number(b);
return a - b;
};
BigEval.prototype.mul = function(a, b){
return Number(a)*Number(b);
return a * b;
};
BigEval.prototype.div = function(a, b){
return Number(a)/Number(b);
return a / b;
};
BigEval.prototype.pow = function(a, b){
return Math.pow(Number(a), Number(b));
return Math.pow(a, b);
};
BigEval.prototype.lessThan = function(a, b){
return a < b;
};
BigEval.prototype.lessThanOrEqualsTo = function(a, b){
return a <= b;
};
BigEval.prototype.greaterThan = function(a, b){
return a > b;
};
BigEval.prototype.greaterThanOrEqualsTo = function(a, b){
return a >= b;
};
BigEval.prototype.equalsTo = function(a, b){
return a == b;
};
BigEval.prototype.notEqualsTo = function(a, b){
return a != b;
};
BigEval.prototype.logicalAnd = function(a, b){
return a && b;
};
BigEval.prototype.logicalOr = function(a, b){
return a || b;
};
BigEval.prototype.fac = function(n){
var s = "1";
n = Number(n);
var s = 1;
for (var i = 2; i <= n; i++)

@@ -344,15 +467,23 @@ s = this.mul(s, i);

BigEval.prototype.mod = function(a, b){
return Number(a)%Number(b);
return a % b;
};
BigEval.prototype.shiftLeft = function(a, b){
return a << b;
};
BigEval.prototype.shiftRight = function(a, b){
return a >> b;
};
BigEval.prototype.and = function(a, b){
return Number(a) & Number(b);
return a & b;
};
BigEval.prototype.xor = function(a, b){
return Number(a) ^ Number(b);
return a ^ b;
};
BigEval.prototype.or = function(a, b){
return Number(a) | Number(b);
return a | b;
};

@@ -366,2 +497,2 @@

module.exports = BigEval;
}
}
{
"name": "bigeval",
"version": "1.2.1",
"version": "2.0.0",
"description": "Mathematical expression solving library",

@@ -5,0 +5,0 @@ "main": "BigEval.js",

# BigEval.js
[![Build Status](https://travis-ci.org/aviaryan/BigEval.js.svg?branch=gh-pages)](https://travis-ci.org/aviaryan/BigEval.js)
[![npm](https://img.shields.io/npm/v/bigeval.svg)]()
[![npm](https://img.shields.io/npm/dm/bigeval.svg)]()
[![Codecov](https://img.shields.io/codecov/c/github/aviaryan/BigEval.js.svg?maxAge=2592000)](https://codecov.io/github/aviaryan/BigEval.js)
[![Code Climate](https://codeclimate.com/github/aviaryan/BigEval.js/badges/gpa.svg)](https://codeclimate.com/github/aviaryan/BigEval.js)
[![Issue Count](https://codeclimate.com/github/aviaryan/BigEval.js/badges/issue_count.svg)](https://codeclimate.com/github/aviaryan/BigEval.js)
[![Codacy Badge](https://api.codacy.com/project/badge/grade/e9e94367b8eb4952a7e0dda5c0dfdf29)](https://www.codacy.com/app/aviaryan/BigEval-js)
[![npm](https://img.shields.io/npm/v/bigeval.svg)](https://www.npmjs.com/package/bigeval)
[![npm](https://img.shields.io/npm/dm/bigeval.svg)](https://www.npmjs.com/package/bigeval)
[![npm](https://img.shields.io/npm/l/bigeval.svg)]()
An alternative to JavaScript's eval() for solving mathematical expressions. It can be extended to use the *Big Number* libraries available to provide results with maximum precision. See [Releases](https://github.com/aviaryan/BigEval.js/releases) for compressed script (~4kb) download.
An alternative to JavaScript's eval() for solving mathematical expressions. It can be extended to use the *Big Number* libraries available to provide results with maximum precision.

@@ -27,3 +31,3 @@

* Full BODMAS/PEMDAS support (just like `Eval`).
* Factorial (!), Power (**), Modulo (%), And (&), Xor (^), Or (|) supported.
* Factorial, Power, Modulo, bitwise and logical operations supported. See [Operators section](#operators) for full list.
* Support for numbers in scientific notation

@@ -36,3 +40,3 @@ * Support for functions. (Math library functions, User functions)

After including *BigEval.js*, the first step is to get a handle to the BigEval object. Then we can use the `exec()` method to solve a expression. See [project page](http://aviaryan.in/BigEval.js/index.html) for a working example.
After including *BigEval.js*, the first step is to create an instance of BigEval. Then we can use the `exec()` method to solve an expression. See [project page](http://aviaryan.in/BigEval.js/index.html) for a working example.
```javascript

@@ -44,2 +48,3 @@ var Obj = new BigEval();

var result4 = Obj.exec("sin( acos( ceil( tan(pi/6) ) ) )"); // sin(0) i.e. 0
var result5 = Obj.exec("((1 << 4) ^ (14 >> 1)) + pi"); // 26.141592653589793
```

@@ -52,11 +57,15 @@ The `exec` method returns the answer as **string**. If an error occurs, then `Obj.err` is set to true and the error message is returned by exec().

The operators currently supported in order of precedence are -
```js
[
['!'], // Factorial
['**'], // power
['/', '*', '%'],
['+', '-'],
['<<', '>>'], // bit shifts
['<', '<=', '>', '>='],
['==', '=', '!='], // equality comparisons
['&'], ['^'], ['|'], // bitwise operations
['&&'], ['||'] // logical operations
]
```
Factorial (!)
Power (**)
Division (/ or \) , Multiplication (*), Modulo (%)
Addition (+), Subtraction (-)
And (&)
Xor (^)
Or (|)
```

@@ -66,6 +75,7 @@

BigEval supports functions like sin(), cos() ... When a function is used in an expression, BigEval first looks into its methods to see if such a function exist, then it looks into the JavaScript `Math()` library and in the end it looks into window's global namespace for the function.
BigEval supports functions like sin(), cos() ... When a function is used in an expression, BigEval first looks into its methods to see if such a function exist, then it looks into the JavaScript's **Math** library and in the end it looks into window's global namespace for the function.
Please note that we use just `sin()` and not `Math.sin()` in expressions. Attaching a new function to BigEval is easy.
```javascript
BigEval.prototype.avg = function(a, b){
var Obj = new BigEval();
Obj.prototype.avg = function(a, b){
return this.div( this.add(a,b) , "2");

@@ -79,3 +89,9 @@ };

Constants are nothing but properties of the BigEval object. To use a constant such as PI in an expression, we can simply write `PI`. Example - `sin( PI / 4 )`.
To add a new constant, we do `Obj.CONSTANT.NAME = VALUE`. The VALUE should be in **string format**. A constant NAME should start with an alphabet and should only use `[a-z0-9_]` characters. Default constants include -
To add a new constant, we do `Obj.CONSTANT.NAME = VALUE`. The VALUE should be in **string format**.
```js
Obj.CONSTANT.INTOCM = '2.54'; // inch to cm
console.log(Obj.exec('12 * intocm')); // the case doesn't matter in expressions
```
A constant NAME should start with an alphabet and should only use `[a-zA-Z0-9_]` characters. Default constants include -
```ini

@@ -101,2 +117,8 @@ PI = 3.1415...

console.log(b.exec('-2 + 3'));
```
```
### Contributors
* [danielgindi](https://github.com/danielgindi)
/**
* Function to round (truncate) a string number to certain places
*/
function roundStr(s, places){
var posDec = s.indexOf('.');
if (posDec == -1)
return s;
else {
var sRounded;
if (places <= 0){
sRounded = s.substr(0, posDec);
} else {
sRounded = s.substr(0, posDec+1+places);
}
return sRounded;
}
}
/**
* Batch test BigEval over randomly generated expressions

@@ -32,26 +14,40 @@ * Compared with eval()'s output

var sz, j, exp, r1, r2;
var ops = "+-/*&^|%"; // 7 (mod can be problem, - divide)
var ops = [
'/', '*', '%',
'+', '-',
'<<', '>>',
'<', '<=', '>', '>=',
'==', '!=',
'&', '^', '|',
'&&', '||'];
try {
eval('1**2'); // Check if current runtime support ** operator
ops.push('**');
} catch (e) {}
for (var i = 0; i<l; i++){
sz = Math.floor((Math.random() * m + 3));
if (sz % 2 == 0)
sz ++;
if (sz % 2 === 0) {
sz++;
}
exp = "";
for (j = 0; j < sz; j++){ // build exp
if (j%2==0)
if (j%2 === 0) {
exp += Math.floor(Math.random() * 20 - 9); // -9
else
exp += ops[ Math.floor(Math.random() * 8) ];
} else {
exp += ops[Math.floor(Math.random() * ops.length)];
}
}
exp = b.plusMinus(exp);
exp = b.plusMinus(exp); // Normalize doubles (--, ++) as eval will consider as postfix/prefix operations
r1 = b.exec(exp);
r2 = eval(exp);
if (r1 != r2){
if ( Math.abs(Number(r1)-r2) > 0.1 ){ // precision
console.log(i + " exp= " + exp + " bigeval= " + r1 + " real= " + r2);
test.equals(0,1);
test.done();
break;
}
if (r1 !== r2 && (!isNaN(r1) || !isNaN(r2))) { // precision
console.log(i + " exp= " + exp + " bigeval= " + r1 + " real= " + r2);
test.equals(r1, r2);
test.done();
break;
}

@@ -67,3 +63,2 @@ }

*/
exports.roundStr = roundStr;
exports.autoTest = autoTest;

@@ -1,3 +0,3 @@

var DecimalBigEval = require('../extensions/MikeMcl-decimal.js');
var cf = require('./common.js');
var DecimalBigEval = require("../extensions/MikeMcl-decimal.js");
var cf = require("./common.js");

@@ -14,3 +14,3 @@ /**

test1: function(test){
test.equals(this.b.exec("12+45*10"), '462');
test.equals(this.b.exec("12+45*10"), 462);
test.done();

@@ -20,3 +20,3 @@ },

test2: function(test){
test.equals(this.b.exec("12/4 * 5 + 45*13 - 72 * 598"), '-42456');
test.equals(this.b.exec("12/4 * 5 + 45*13 - 72 * 598"), -42456);
test.done();

@@ -26,3 +26,3 @@ },

testMulDiv: function(test){
test.equals(cf.roundStr(this.b.exec("345 / 23 * 124 / 41 * 12"), 0), '544');
test.equals(cf.roundStr(this.b.exec("345 / 23 * 124 / 41 * 12"), 0), 544);
test.done();

@@ -29,0 +29,0 @@ }

@@ -1,3 +0,3 @@

var BigEval = require('../BigEval.js');
var cf = require('./common.js');
var BigEval = require("../BigEval.js");
var cf = require("./common.js");

@@ -14,3 +14,3 @@ /**

test1: function(test){
test.equals(this.b.exec("12+45*10"), '462');
test.equals(this.b.exec("12+45*10"), 462);
test.done();

@@ -20,3 +20,3 @@ },

test2: function(test){
test.equals(this.b.exec("12/4 * 5 + 45*13 - 72 * 598"), '-42456');
test.equals(this.b.exec("12/4 * 5 + 45*13 - 72 * 598"), -42456);
test.done();

@@ -26,3 +26,3 @@ },

testMulDiv: function(test){
test.equals(cf.roundStr(this.b.exec("345 / 23 * 124 / 41 * 12"), 0), '544');
test.equals(Math.round(this.b.exec("345 / 23 * 124 / 41 * 12")), 544);
test.done();

@@ -38,3 +38,3 @@ }

var b = new BigEval();
test.equals(b.exec("12+45*10"), ''+462);
test.equals(b.exec("12+45*10"), 462);
test.done();

@@ -41,0 +41,0 @@ };

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc