Get around floating point precision of JavaScript fixes #5

Fix `equation` not working on parentheses wrapped variables
Fixed `parseExpression` not working correctly on nested function operators
This commit is contained in:
Mahdi Dibaiee
2015-06-18 15:37:42 +04:30
parent 75969a4e1a
commit 2b3c06c413
6 changed files with 101 additions and 17 deletions

View File

@ -49,7 +49,11 @@ let Equation = {
let stack = parseExpression(expression);
let variables = [];
stack.forEach(a => {
stack.forEach(function varCheck(a) {
if (Array.isArray(a)) {
return a.forEach(varCheck);
}
if (typeof a === 'string' && !_.isNumber(a) &&
!operators[a] && a === a.toLowerCase()) {
// grouped variables like (y) need to have their parantheses removed
@ -125,23 +129,32 @@ const parseExpression = expression => {
}
// it's probably a function with a length more than one
if (!_.isNumber(cur) && !operators[cur] && cur !== '.') {
if (!_.isNumber(cur) && !operators[cur] && cur !== '.' &&
cur !== '(' && cur !== ')') {
record += cur;
} else if (record.length) {
stack.push(record, cur);
record = '';
} else if (_.isNumber(stack[stack.length - 1]) &&
} else if (_.isNumber(stack[past]) &&
(_.isNumber(cur) || cur === '.')) {
stack[stack.length - 1] += cur;
} else if (stack[past] === '-') {
const beforeSign = stack[stack.length - 2];
stack[past] += cur;
// negation sign
} else if (stack[past] === '-') {
const beforeSign = stack[past - 1];
// 2 / -5 is OK, pass
if (operators[beforeSign]) {
stack[past] += cur;
// (2+1) - 5 becomes (2+1) + -5
} else if (beforeSign === ')') {
stack[past] = '+';
stack.push(`-${cur}`);
// 2 - 5 is also OK, pass
} else if (_.isNumber(beforeSign)) {
stack.push(cur);
} else {
@ -272,12 +285,13 @@ const evaluate = stack => {
if (!op) {
return stack[0];
}
const { left } = formatInfo(op);
let leftArguments = stack.slice(0, left),
rightArguments = stack.slice(left + 1);
return operators[op].fn(...leftArguments, ...rightArguments);
return fixFloat(operators[op].fn(...leftArguments, ...rightArguments));
};
/**
@ -315,4 +329,16 @@ const replaceConstants = expression => {
});
};
/**
* Fixes JavaScript's floating point precisions - Issue #5
*
* @param {Number} number
* The number to fix
* @return {Number}
* Fixed number
*/
const fixFloat = number => {
return +number.toFixed(15);
};
export default Equation;

View File

@ -88,5 +88,15 @@ export default {
fn: Math.cot,
format: '10',
precedence: -1
},
'round': {
fn: Math.round,
format: '10',
precedence: -1
},
'floor': {
fn: Math.floor,
format: '10',
precedence: -1
}
};