Last active
March 28, 2020 15:28
-
-
Save toaco/685f65338def404a012e6002c34a2f70 to your computer and use it in GitHub Desktop.
A simple four arithmetic operations implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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