`
hxzon
  • 浏览: 17885 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

FormulaParser公式解析类

阅读更多
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))); 
                } 
        } 
} 
分享到:
评论

相关推荐

    文本公式解析组件

    使用运算树进行解释,大大提高了公式的解析效率 支持 + - * / ^ %三角函数: 比较运算: FormulaParser fp = new FormulaParser(); fp.AddParameter ("a","100"); fp.AddParameter("b", "20"); fp.AddParameter("c", ...

    formula-parser:Javascript库解析Excel公式等

    公式解析器 库提供了一个Parser类,用于评估excel和数学公式。安装建议的安装公式分析器的方法是使用以下命令通过 : $ npm install hot-formula-parser --save Node.js: var FormulaParser = require ( 'hot-...

    用BeanShell实现公式管理

    - **FormulaParser**:负责解析用户定义的公式,将其转换为系统可识别的格式,并保存到公式库中。 - **Calculator**:执行计算任务,包含各种运算符,可以根据需求扩展。 - **Formula**:表示单个公式,封装了...

    公式解析器:解析和评估以字符串形式给出的数学公式

    公式解析器 Formula Parser是用于解析和评估以字符串形式给出的数学公式的库。 支持: 运算符:+,-,*,/,^ 变量:x,y,z,a,b 小数点为“。”的数字E表示法中的数字常数:pi,e,Inf 功能:sqrt,abs,sin,cos...

    使用java处理字符串公式运算的方法

    在实际编程中,我们可以创建一个解析器类 `FormulaParser`,该类包含一个正则表达式来匹配公式中的变量占位符(如 `#{dddd}`)。`parse` 方法接收公式字符串、中间公式映射(`formulas`)和基础数据映射(`values`)...

Global site tag (gtag.js) - Google Analytics