FormulaParser公式解析类 使用新的计算函数,新的算法.速度更快,使用更方便. 算法简介: format函数: 根据格式化的原则,用一系列的if判断,过滤掉不符合的字符,并分割成数组.再利用括号的一一对应,补全 不匹配的括号. calculate函数: 根据运算法则,给不同运算符赋予不同权值,再通过权值比较便可以确定运算顺序. 类代码: /* * FormulaPareser 公式解析类 * Version 1.0 * 2006.8.11 * Copyright CYJB */ // /* * 公式解析类,可以计算包含加号(+),减号(-),乘号(*),除号(/),乘方(^),取模(%)以及括号的公式. * format()格式化公式.格式化遵循以下原则: * 1."+","-"号前是非数字时,将被认为是正、负号. * 2.当两个运算符连用(例如"^*"),将使用后面的运算符("+""-"除外).若前面的运算符是"+","-",将被 认为是+1,-1. * 3.括号前后直接加数字,将被认为是乘以该数字. * 4.当"("与")"不匹配时,将认为是缺少最外层括号. * 5.自动去除公式的非法字符(除了".0123456789+-/*%^()"). * 6.自动去除"(数字)"中的括号 * calculate()计算公式.可以传入字符串(会自动调用format函数格式化字符串),也可以直接传入数组 * (不会调用format函数).直接传入数组需要注意格式,但是计算会更快速. * 注意:请注意输入数据的大小,否则可能会计算错误(超过flash计算能力). */ // class FormulaParser { public static function format(s:String):Array { //格式化公式 var data:Array = []; var backets:Array = []; //括号个数记录 var n = 0; var s1 = s.charAt(n); while (s1.length == 1) { var k = s1.charCodeAt(0); var l = data.length-1; var s2 = data[l]; var k2 = (s2.charCodeAt(s2.length-1) == undefined) ? 0 : s2.charCodeAt(s2.length-1); if (k>=48 && k<=57) { //trace("这个是数字"); if (k2 == 46 || (k2>=48 && k2<=57)) { //trace("前面是数字或."); data[l] += s1; } else if (s2 == "--") { //trace("前面是负号"); data[l] = "-"+s1; } else if (s2 == ")") { //trace("前面是)"); data.push("*"); data.push(s1); } else { //trace("前面是开头或+-*/%^或("); data.push(s1); } } else if (k == 46) { //trace("这个是."); if (k2>=48 && k2<=57) { //trace("前面是数字"); if (s2.indexOf(".") == -1) { //只能有一个小数点 data[l] += s1; } } else if (s2 == "--") { //trace("前面是负号"); data[l] = "-0."; } else if (s2 == ")") { //trace("前面是)"); data.push("*"); data.push("0."); } else if (k2 != 46) { //trace("前面是开头或+-*/%^或("); data.push("0."); } } else if (k == 43 || k == 45) { //trace("这个是+-"); if (k2 == 41 || (k2>=48 && k2<=57)) { //trace("前面是数字或)"); data.push(s1); } else if (k2 == 46) { //trace("前面是."); data[l] = data[l].slice(0, -1); data.push(s1); } else if (k == 45) { //trace("这个是-"); if (s2 == "--") { //trace("前面是负号"); data.pop(); } else if (k2 == 45) { //trace("前面是-"); data[l] = "+"; } else if (k2 == 43) { //trace("前面是+"); data[l] = "-"; } else { //trace("前面是开头或+-*/%^或("); data.push("--"); } } } else if (k == 37 || k == 42 || k == 47 || k == 94) { //trace("这个是*/%^"); if (k2 == 41 || (k2>=48 && k2<=57)) { //trace("前面是数字或)"); data.push(s1); } else if (k2 == 46) { //trace("前面是."); data[l] = data[l].slice(0, -1); data.push(s1); } else if (s2 == "--") { //trace("前面是负号"); data[l] = "-1"; data.push(s1); } else if (k2 == 45 || k2 == 43) { //trace("前面是+-"); data.push("1"); data.push(s1); } else if (s2 != undefined && k2 != 40) { //trace("前面是*/%^"); data[l] = s1; } } else if (s1 == "(") { //trace("这个是("); backets.push("("); if (k2 == 41 || (k2>=48 && k2<=57)) { //trace("前面是数字或)"); data.push("*"); data.push("("); } else if (k2 == 46) { //trace("前面是."); data[l] = data[l].slice(0, -1); data.push("*"); data.push("("); } else if (s2 == "--") { //trace("前面是负号"); data[l] = "-1"; data.push("*"); data.push("("); } else { //trace("前面是开头或+-*/%^或("); data.push("("); } } else if (s1 == ")") { //trace("这个是)"); if (s2 != undefined) { if (backets[backets.length-1] == "(") { backets.pop(); } else { backets.push(")"); } } if (k2 == 41 || (k2>=48 && k2<=57)) { //trace("前面是数字或)"); data.push(")"); } else if (s2 == "--") { //trace("前面是负号"); data[l] = "-1"; data.push(")"); } else if (k2 == 46) { //trace("前面是."); data[l] = data[l].slice(0, -1); data.push(")"); } else if (k2 == 40) { //trace("前面是("); data.pop(); } else if (s2 != undefined) { //trace("前面是+-*/%^"); data[l] = ")"; } } n++; s1 = s.charAt(n); } //防止最后一位不合理 while (data[data.length-1] == "(") { data.pop(); backets.pop(); } var m = data[data.length-1]; if (m == "+" || m == "-" || m == "*" || m == "/" || m == "%" || m == "^") { data.pop(); } else if (m == "--") { data.pop(); data.pop(); } else if (m.substr(-1) == ".") { data[data.length-1] = m.slice(0, -1); } //防止括号不匹配 var bs = backets.join(""); var n1 = bs.split("(").length; var n2 = bs.split(")").length; if (n1 != 0) { n1--; } if (n2 != 0) { n2--; } while (n1--) { data.push(")"); } while (n2--) { data.splice(0, 0, "("); } //去除"(数字)"中的括号 var i = 1; //第一、二位不可能是")" while (i++<data.length) { if (data == ")") { if (data[i-2] == "(") { data.splice(i, 1); data.splice(i-2, 1); i -= 2; } } } return data; } public static function calculate(s):Number { //计算公式 var data:Array = []; //参数的类型检察 if (s instanceof Array) { data = s; } else if (typeof (s) == "string") { data = format(s); } var m:Array = []; //括号数据存储 var num:String = "0"; var l = data.length; var sign:String = "+"; var n:Number = 0; var i = 0; while (i<l) { if (data == "(") { m.push([num, sign, n, false]); if (data[i+1] == "(") { i++; num = "0"; sign = "+"; n = 0; } else { num = data[i+1]; sign = data[i+2]; , n = getPriority(sign); i += 3; } } else { var sign2 = data[i+1]; if (sign2 == ")") { num = evals(num, sign, data); while (m[m.length-1][3]) { var arr = m.pop(); num = evals(arr[0], arr[1], num); } m[m.length-1][3] = true; while (data[i+2] == ")") { while (m[m.length-1][3]) { var arr = m.pop(); num = evals(arr[0], arr[1], num); } m[m.length-1][3] = true; i++; } sign = data[i+2]; n = getPriority(sign); while (m[m.length-1][2]>=n && m[m.length-1][3]) { var arr = m.pop(); num = evals(arr[0], arr[1], num); } i += 3; if (i>=l) { for (var j in m) { num = evals(m[j][0], m[j][1], num); } } } else { var n2 = getPriority(sign2); if (n>=n2) { num = evals(num, sign, data); while (m[m.length-1][2]>=n2 && m[m.length- 1][3]) { var arr = m.pop(); num = evals(arr[0], arr[1], num); } } else { m.push([num, sign, n, true]); num = data; } sign = sign2; n = n2; i += 2; } } } return Number(num); } private static function getPriority(s:String):Number { //计算权值 if (s == "+" || s == "-") { return 1; } else if (s == "*" || s == "/" || s == "%") { return 2; } else if (s == "^") { return 3; } else { return 0; } } private static function evals(n1:String, s:String, n2:String):String { //计算数据 switch (s) { case "+" : return String(Number(n1)+Number(n2)); case "-" : return String(Number(n1)-Number(n2)); case "*" : return String(Number(n1)*Number(n2)); case "/" : return String(Number(n1)/Number(n2)); case "%" : return String(Number(n1)%Number(n2)); case "^" : return String(Math.pow(Number(n1), Number(n2))); } } }