root/as3/Calculator/Calculator.as

リビジョン 131, 5.1 kB (コミッタ: yossy, コミット時期: 1 年 前)

Moved dada, doke and fladdict repositories.

Line 
1 /**
2  * String形式の数式を計算するクラス
3  *
4  * code is originally from
5  * http://ericlin2.tripod.com/math2/EvaluateEqMxt.html
6  *
7  * 改造点
8  *      ・ユーザー定義変数を使用可能にした。
9  *      ・ユーザー定義関数も使用可能にした。
10  *
11  * var num1 : Number = Calculator.evaluate("pow(2,4)");
12  * var num2 : Number = Calculator.evaluate("(x+y)*2", {x:5, y:3});
13  * var num3 : Number = Calculator.evaluate("f()*2", {f:function():void{return 5}});
14  */
15 package
16 {
17         public class Calculator
18         {
19                 public static const operatorSet : String = "+-*/^+-";
20                 protected static var _argObj : Object
21                
22                
23                 /**
24                  * @param str 数式。Math関数はsqrt(a,b)といった形で使用可能。
25                  * @param argObj ユーザー定義変数。ここで{x:1}等と定義することで、数式内で変数が使える
26                  */
27                 public static function evaluate(str : String, argObj:Object=null) : Number
28                 {
29                         //ユーザー定義変数を一時保存
30                         argObj = (argObj)? argObj : {};
31                        
32                         str = str.split(" ").join("");
33                         //trim off the space if any
34                         if (!str.length>0) {
35                                 return 0;
36                         }
37                         // search for  +,-,*,/,*    , skip string in parenthesis and cut into two pieces accordingly
38                         // after this step ,  only function, parenthesis, variable or number are  left
39                         var str2 : String = maskParenthesis(str);
40                         for (var k :int = 0; k<operatorSet.length; k++) {
41                                 // becareful, we should check from right to left, not left to right
42                                 var op : String = operatorSet.charAt(k);
43                                 var start : Number= str.length-1;
44                                 var i : int = 0;
45                                 while ((i=str2.lastIndexOf(op, start))>=0) {
46                                         if ((k<=1) && operatorSet.indexOf(str2.charAt(i-1))>=0) {
47                                                 //something like 3*-4; 
48                                                 start = i-1;
49                                                 //################continue
50                                                 continue;
51                                         }
52                                         var lStr : String = str.substr(0, i);
53                                         var rStr : String = str.substr(i+1, str.length-i-1);
54                                         return handleOperator(op, lStr, rStr, argObj);
55                                 }
56                         }
57                         // now we get only the parenthesis, function and pure number/variable here; now check function
58                         start = str.indexOf("(");
59                         if (start>=0) {
60                                 var functionName : String = (str.substr(0, start)).toLowerCase();
61                                 var contentInParenthesis : String = str.substr(start+1, str.length-start-2);
62                                 return handleFunction(functionName, contentInParenthesis, argObj);
63                         }
64                         // After those steps , only variable and pure number are left here, now check variable
65                         if (isNaN(Number(str))) {
66                                 //ここでユーザー定義変数も使えるように改造
67                                 if( Math[str]!=undefined ){
68                                         return Math[str];
69                                 }else if(argObj[str]!=undefined && argObj[str] is Number){
70                                         return argObj[str];
71                                 }
72                         }
73                         // variable are screened off, here is pure value
74                         return Number(str);
75                 };
76                
77                
78                 protected static function handleOperator(operator:String, lStr:String, rStr:String, argObj:Object):Number
79                 {
80                         var num1 : Number = evaluate(lStr, argObj);
81                         var num2 : Number = evaluate(rStr, argObj);
82                         var val : Number
83                         switch (operator) {
84                                 case "+" :
85                                         val = num1+num2;
86                                         break
87                                 case "-" :
88                                         val =  num1-num2;
89                                         break
90                                 case "*" :
91                                         val =  num1*num2;
92                                         break
93                                 case "/" :
94                                         val =  num1/num2;
95                                         break
96                                 case "^" :
97                                         val = Math.pow(num1, num2);
98                                         break
99                                 default :
100                                         val = 0;
101                         }
102                         return val
103                 }
104                
105                
106                 /**
107                  * random 等引数0の呼び出しがあまりうまくいかなかったので色々改造
108                  */
109                 protected static function handleFunction(functionName : String, contentInParenthesis:String, argObj:Object) : Number
110                 {
111                         if (!functionName.length>0) {
112                                 // pure parenthesis
113                                 return evaluate(contentInParenthesis, argObj);
114                         }
115                         // It is a function, now check how many parameters
116                         var str2 :String = maskParenthesis(contentInParenthesis);
117                         var str : String = contentInParenthesis;
118                         var params : Array = [];
119                        
120                         if( str!="" && str2 !=""){
121                                 var i : * = -1;
122                                 while (i=str2.indexOf(",")>=0) {
123                                         var lStr : String = str.substr(0, i);
124                                         str2 = str2.substr(i+1, str2.length-i-1);
125                                         str  = str.substr(i+1, str.length-i-1);
126                                         params.push(evaluate(lStr, argObj));
127                                 }
128                                 params.push(evaluate(str, argObj));
129                         }
130                        
131                         var val:Number
132                        
133                         if(Math[functionName]!=undefined)
134                         {
135                                 val = Math[functionName].apply(null, params);
136                         }else if(argObj[functionName]!=undefined){
137                                 val = argObj[functionName].apply(null, params);
138                         }
139                                                
140                         return val;
141                 }
142
143                
144                
145                 // ()内部をマスクする。
146                 /**
147                  * 5+4*(4-3)+2 が 5+4*(((((+2 になる?
148                  *
149                  */
150                 protected static function maskParenthesis( str : String ) : String
151                 {
152                         var parenthesisStack : Number = 0;
153                         var temp : String = "";
154                         for( var i : int = 0; i < str.length; i++ )
155                         {
156                                 var char :String = str.substr(i, 1);
157                                 if( char == "(" ){
158                                         parenthesisStack++;
159                                 }
160                                 if( char == ")" ){
161                                         parenthesisStack--;
162                                 }
163                                 temp += (parenthesisStack == 0 ? char : "(");
164                         }
165                         if( parenthesisStack != 0 ){
166                                 // "(" と ")" の数が合わない
167                                 throw new Error("The number of ( and ) does not match");
168                                 return "";
169                         }
170                         return temp;
171                 }
172         }
173 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。