Created
November 18, 2019 04:20
-
-
Save paxbun/decf250fbbce297a156dc27871fdc2fd to your computer and use it in GitHub Desktop.
Advanced calculator
This file contains hidden or 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
| * { | |
| font-size: large; | |
| } | |
| #input { | |
| padding: 4px; | |
| min-width: 10px; | |
| border-bottom: 1px; | |
| } |
This file contains hidden or 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
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <link rel="stylesheet" href="index.css"> | |
| <script src="index.js"></script> | |
| </head> | |
| <body> | |
| <span contenteditable="true" id="input"></span> | |
| <span id="output"></span> | |
| </body> | |
| </html> |
This file contains hidden or 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 ops = "+-*/^()"; | |
| const nums = "0123456789"; | |
| function split(expr) { | |
| let rtn = []; | |
| let stack = ''; | |
| for (let i = 0; i < expr.length; ++i) { | |
| if (ops.includes(expr[i])) { | |
| if (stack.length != 0) | |
| rtn.push(stack); | |
| rtn.push(expr[i]); | |
| stack = ''; | |
| } else if (nums.includes(expr[i])) { | |
| stack = stack + expr[i]; | |
| } else { | |
| return undefined; | |
| } | |
| } | |
| if (stack.length != 0) | |
| rtn.push(stack); | |
| return rtn; | |
| } | |
| function in2pre(expr) { | |
| let precedence = { | |
| '(' : 0, | |
| ')' : 0, | |
| '^' : 1, | |
| '*' : 2, | |
| '/' : 2, | |
| '+' : 3, | |
| '-' : 3 | |
| }; | |
| let stack = []; | |
| let result = []; | |
| for (let i = 0; i < expr.length; ++i) { | |
| if ("+-*/^".includes(expr[i])) { | |
| let pre = precedence[expr[i]]; | |
| if (stack.length == 0 || stack[stack.length - 1][1] > pre) { | |
| stack.push([expr[i], precedence[expr[i]]]); | |
| } else { | |
| while (stack.length != 0 | |
| && stack[stack.length - 1][0] != '(' | |
| && stack[stack.length - 1][1] <= pre) | |
| result.push(stack.pop()[0]); | |
| stack.push([expr[i], pre]); | |
| } | |
| } else if (expr[i] == '(') { | |
| stack.push([expr[i], 0]); | |
| } else if (expr[i] == ')'){ | |
| if (stack.length == 0) | |
| return undefined; | |
| while (stack[stack.length - 1][0] != '(') | |
| result.push(stack.pop()[0]); | |
| stack.pop(); | |
| } | |
| else { | |
| result.push(expr[i]); | |
| } | |
| } | |
| for (let i = stack.length - 1; i >= 0; --i) { | |
| result.push(stack[i][0]); | |
| } | |
| return result; | |
| } | |
| function calc(expr) { | |
| if (expr == undefined) | |
| return undefined; | |
| function calc_internal(beg) { | |
| if (beg < 0) | |
| return undefined; | |
| if (ops.includes(expr[beg])) { | |
| let right = calc_internal(beg - 1); | |
| if (right == undefined) | |
| return undefined; | |
| let left = calc_internal(right[1]); | |
| if (left == undefined) | |
| return undefined; | |
| let op = { | |
| '^' : (x, y) => Math.pow(x, y), | |
| '*' : (x, y) => x * y, | |
| '/' : (x, y) => x / y, | |
| '+' : (x, y) => x + y, | |
| '-' : (x, y) => x - y | |
| } | |
| return [op[expr[beg]](Number(left[0]), Number(right[0])), left[1]]; | |
| } else { | |
| return [Number(expr[beg]), beg - 1]; | |
| } | |
| } | |
| let result = calc_internal(expr.length - 1); | |
| if (result == undefined) | |
| return undefined; | |
| else | |
| return result[0]; | |
| } | |
| function run() { | |
| let input_dom = document.getElementById('input'); | |
| let output_dom = document.getElementById('output'); | |
| const input = input_dom.innerHTML; | |
| if (input.length == 0) | |
| output_dom.innerHTML = ''; | |
| const result = calc(in2pre(split(input))); | |
| if (result != undefined && !isNaN(result)) | |
| output_dom.innerHTML = '=' + result; | |
| } | |
| window.onload = function() { | |
| document.getElementById('input').addEventListener('input', run); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment