//Converts a infix expression to postfix String.prototype.ToPostfix = function () { var Stack = ""; var Token = ""; var Result = ""; var Angle = "Radian"; for (var i = 0; i < this.length; i++) { Token = this.charAt(i); switch (Token) { case "(": Stack += "("; break; case ")": while (Stack.length > 0 && Stack.charAt(Stack.length - 1) != "(") { Result += Stack.charAt(Stack.length - 1); Stack = Stack.substring(0, Stack.length - 1); } Stack = Stack.substring(0, Stack.length - 1); break; case "^": case "*": case "/": case "+": PopStack(); break; default: if (Token == "-" && i > 0 && /[^(\^*/+-]/.test(this.charAt(i - 1))) { PopStack("-"); break; } while (/[^()\^*/+-]/.test(this.charAt(i + 1)) && i < this.length) { Token += this.charAt(i++ + 1); } if (/\+|-/.test(this.charAt(i + 1))) { if (/e/i.test(this.charAt(i)) && i > 0 && /\d/.test(this.charAt(i - 1))) { Token += this.charAt(i++ + 1); while (/[^()\^*/+-]/.test(this.charAt(i + 1)) && i < this.length) { Token += this.charAt(i++ + 1); } } } if (this.charAt(i + 1) == "(") { try { if (typeof(Math[Token.toLowerCase()])=="function" || eval("typeof("+(Token.toLowerCase())+")=='function'")) { var firstChar = this.charAt(i-Token.length); if (eval("typeof("+Token+")!='function'")) { Token = "Math." + Token.toLowerCase(); } Token += this.charAt(i++ + 1); var ParamToken = ""; var Parentheses = 0; while ((/[^)]/.test(this.charAt(i + 1)) || Parentheses > 0) && i < this.length) { if (this.charAt(i + 1) == "(") Parentheses++; else if (this.charAt(i + 1) == ")") Parentheses--; ParamToken += this.charAt(i++ + 1); } var Params = ParamToken.split(/\s*,\s*/); for (Index in Params) { Params[Index] = Params[Index].Calculate(); } Token += Params.join(","); Token += this.charAt(i++ + 1); if (/^Math\.(sin|cos|tan)\((.+)\)$/.test(Token)) { var Func = "Math." + RegExp.$1 + "(" + RegExp.$2 + "*Math.PI"; if (/^degrees?$/i.test(Angle)){ Token = Func + "/180)"; } else if (/^grad$/i.test(Angle)) { Token = Func + "/200)"; } } if (/^Math\.(a(?:sin|cos|tan2?))\((.+)\)$/.test(Token)) { var Func = "Math." + RegExp.$1 + "(" + RegExp.$2 + ")/Math.PI"; if (/^degrees?$/i.test(Angle)){ Token = Func + "*180"; } else if (/^grad$/i.test(Angle)) { Token = Func + "*200"; } } if(firstChar == "-") Token = "-" + Token; } else { PopStack("*"); } } catch (e) { Debug.Trace("! "+e.description); return undefined; } } Result += "\x01" + Token + "\x01"; break; } } while (Stack.length > 0) { Result += Stack.charAt(Stack.length - 1); Stack = Stack.substring(0, Stack.length-1); } return Result.replace(/\s/g, ""); function PopStack (Operator) { if (Operator == undefined) Operator = Token; while (Stack.length > 0 && ((/[\^*/+-]/.test(Operator) && /[\^]/.test(Stack.charAt(Stack.length - 1))) || (/[*/+-]/.test(Operator) && /[*/]/.test(Stack.charAt(Stack.length - 1))) || (/[+-]/.test(Operator) && /[+-]/.test(Stack.charAt(Stack.length - 1))))) { Result += Stack.charAt(Stack.length - 1); Stack = Stack.substring(0, Stack.length - 1); } Stack += Operator; } } //Calculates a postfix expression String.prototype.CalculatePostfix = function () { var Stack = new Array(); var Token = ""; for (var i = 0; i < this.length; i++) { Token = this.charAt(i); if (/[^\^*/+-]/.test(Token)) { while (/[^\x01]/.test(this.charAt(i + 1)) && i < this.length) { Token += this.charAt(i++ + 1); } Token += this.charAt(i++ + 1); if (/\+|-/.test(this.charAt(i + 1))) { if (/e/i.test(this.charAt(i)) && i > 0 && /\d/.test(this.charAt(i - 1))) { Token += this.charAt(i++ + 1); while (/[^()\^*/+-]/.test(this.charAt(i + 1)) && i < this.length) { Token += this.charAt(i++ + 1); } } } if (/\x01(.+)\x01/.test(Token)) { var Operands = RegExp.$1.split(/\x01\x01/); for (Index in Operands) { var tmpOperand = Operands[Index]; if(/^\-/.test(tmpOperand)) tmpOperand = tmpOperand.substr(1); if(/^([^()\^*/+-]+)!$/.test(tmpOperand)) tmpOperand = tmpOperand.substr(0, (tmpOperand.length-1)); if(eval("typeof("+tmpOperand+")=='undefined'")) { if (typeof(Math[tmpOperand.toUpperCase()]) != "undefined" && typeof(Math[tmpOperand.toLowerCase()]) != "function") { if(/^\-/.test(Operands[Index])) { Operands[Index] = -1 * Math[Operands[Index].substr(1).toUpperCase()]; } else { Operands[Index] = Math[Operands[Index].toUpperCase()]; } } else if (/^\-?(h|b|o)/.test(Operands[Index])) { var base = 10; switch(RegExp.$1) { case "h": base = 16; break; case "b": base = 2; break; case "o": base = 8; break; } if(Operands[Index].length != tmpOperand.length) { Operands[Index] = parseInt(Operands[Index].substr(2), base) * -1; } else { Operands[Index] = parseInt(Operands[Index].substr(1), base); } } } else if(eval("typeof("+tmpOperand+")=='number'")) { if (/^([^()\^*/+-]+)!$/.test(Operands[Index])) { Operands[Index] = String(Fac(RegExp.$1 * 1)); } } } Stack = Stack.concat(Operands); } else { return undefined; } } else { if (Stack.length >= 2) { if (Token == "^") { Stack[Stack.length - 2] = Math.pow(eval(Stack[Stack.length - 2]), eval(Stack[Stack.length - 1])); } else { Stack[Stack.length - 2] = eval(eval(Stack[Stack.length - 2]) + Token + eval(Stack[Stack.length - 1])); } Stack.pop(); } } } try { if (/=/.test(Stack[0])) { if(/^x=(.+)$/i.test(Stack[0])) Stack[0] = eval("x=" + eval(RegExp.$1)); else Stack[0] = "NaN"; } var n = eval(Stack[0]); if(isNaN(n) || Stack[0] == "NaN") { //Check for NaN n = "NaN"; } else if(!isFinite(n) || Stack[0] == "Infinity") { //Check for infinity n = "Infinity"; } else { LastCalc = n; } return n; } catch (e) { return undefined; } } //Calculates an infix expression String.prototype.Calculate = function () { //String clean-up var Infix = this.replace(/\s/g, ""); //Spaces removal Infix = Infix.replace(/,/g, "."); //Comma to dot Infix = Infix.replace(/ans/gi, LastCalc); //Ans to last answer Infix = Infix.replace(/\u00B2/g, "^2"); //² = to power 2 Infix = Infix.replace(/\u00B3/g, "^3"); //³ = to power 3 //String to postfix var Postfix = Infix.ToPostfix(); //Calculate postfix if (Postfix != undefined) return Postfix.CalculatePostfix(); }