Skip to content

Instantly share code, notes, and snippets.

@toaco
Last active March 28, 2020 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toaco/685f65338def404a012e6002c34a2f70 to your computer and use it in GitHub Desktop.
Save toaco/685f65338def404a012e6002c34a2f70 to your computer and use it in GitHub Desktop.
A simple four arithmetic operations implementation
const Decimal = require('decimal.js');
// 计算表达式的值
function calculate(expression) {
const words = splitExpression(expression);
const outputs = [];
const signs = [];
while (words.length) {
const word = words.shift();
if (!isNaN(word)) {
outputs.push(new Decimal(word));
continue;
}
while (signs.length) {
const sign = signs.pop();
if (!higher(word, sign)) {
outputs.push(sign)
} else {
signs.push(sign);
break
}
}
signs.push(word)
}
while (signs.length) {
outputs.push(signs.pop())
}
const result = [];
outputs.forEach(word => {
if (isNaN(word)) {
const right = result.pop();
const left = result.pop();
result.push(binaryOperate(left, word, right))
} else {
result.push(word)
}
});
return result.pop();
}
// 把表达式分割为 运算符 和 数字
// 示例:
// splitExpression("-1*-3+-2") 的结果为 ["-1", "*", "-3", "+", "-2"]
function splitExpression(expression) {
const words = expression.split(/((?<!\d)[+-]?\d*\.?\d*)/);
return words.filter(word => word)
}
// 判断 sign1 的优先级是否比 sign2 高
function higher(sign1, sign2) {
return ["*", "/"].includes(sign1) && ["-", "+"].includes(sign2);
}
// 二元运算,包括加减乘除
function binaryOperate(left, operator, right) {
switch (operator) {
case "+":
return left.plus(right);
case "-":
return left.minus(right);
case "*":
return left.times(right);
case "/":
return left.div(right);
}
}
// 测试
const assert = require('assert');
assert.equal(calculate("1+2"), 3);
assert.equal(calculate("1-2"), -1);
assert.equal(calculate("1*2"), 2);
assert.equal(calculate("1/2"), 0.5);
assert.equal(calculate("1+2/2/4"), 1.25);
assert.equal(calculate("1*2+2/4"), 2.5);
assert.equal(calculate("1*2*3+2/2/4*1-2"), 4.25);
assert.equal(calculate("-1*-3+-2"), 1);
assert.equal(calculate("1*2*3+2/2/4*1-2"), 4.25);
assert.equal(calculate("-1*-3+-2/-1"), 5);
assert.equal(calculate("-1*-2*-3-4"), -10);
assert.equal(calculate("0.1+0.1"), 0.2);
assert.equal(calculate(".1+.1"), 0.2);
assert.equal(calculate("0.+.1"), 0.1);
assert.equal(calculate("0.1+0.2"), 0.3);
assert.equal(calculate("0.1+0.1+0.1+0.2+0.3"), 0.8);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment