2007/12/13 | Expression数学表达式求值AS2.0版本
类别(Flash习作) | 评论(0) | 阅读(311) | 发表于 17:02

//用例:
//estr="sum(1,2,3,sin((4+5)*10),acos(cos(70)),avg(1,2,3,4,5,6,7,8,9))+2e+4";

//Expression.evaluate(estr);

/**
 * @author jh7086
 */
class Expression {
 //为方便检测"+ -"是否为正负号,限用单个字符的运算符
 private static var ostr : String = "+,-,*,/,%,^,e";
 private static var oarr : Array = ostr.split(",");
 private static var fstr : String = "abs,round,sqrt,sin,cos,tan,acos,asin,atan,log,exp,sum,avg,count,max,min";
 private static var farr : Array = fstr.split(",");
 //
 public static function evaluate(estr : String) : String {
  trace(estr);
  return reckon2(estr).toString();
 }

 public static function listOperators() : String {
  return ostr;
 }

 public static function listFunctions() : String {
  return fstr;
 }

 //运算符及函数的具体运算
 private static function func(optr : String, va : Array) : Number {
  var i : Number;
  if (typeof (va[0]) == "object") {
   for (i in va[0]) {
    va[i] = _Number(va[0][i]);
   }
  } else {
   for (i in va) {
    va[i] = _Number(va[i]);
   }
  }
  switch (optr) {
   case "+" :
    return va[0] + va[1];
   case "-" :
    return va[0] - va[1];
   case "*" :
    return va[0] * va[1];
   case "/" :
    return va[0] / va[1];
   case "%" :
    return va[0] % va[1];
   case "^" :
    return Math.pow(va[0], va[1]);
   case "e" :
    return va[0] * Math.pow(10, va[1]);
   case "abs" :
    return Math.abs(va[0]);
   case "round" :
    return Math.round(va[0]);
   case "sqrt" :
    return Math.sqrt(va[0]);
   case "sin" :
    return Math.sin(va[0] / 180 * Math.PI);
   case "cos" :
    return Math.cos(va[0] / 180 * Math.PI);
   case "tan" :
    return Math.tan(va[0] / 180 * Math.PI);
   case "acos" :
    return Math.acos(va[0]) * 180 / Math.PI;
   case "asin" :
    return Math.asin(va[0]) * 180 / Math.PI;
   case "atan" :
    return Math.atan(va[0]) * 180 / Math.PI;
   case "log" :
    return Math.log(va[0]);
   case "exp" :
    return Math.exp(va[0]);
   case "sum" :
    return sum(va);
   case "avg" :
    return sum(va) / va.length;
   case "count" :
    return va.length;
   case "max" :
    return max(va);
   case "min" :
    return min(va);
  }
 }

 //获取运算符的优先级,非运算符的优先级为0
 private static function isp(optr : String) : Number {
  switch (optr) {
   case "+" :
   case "-" :
    return 1;
   case "*" :
   case "/" :
   case "%" :
    return 2;
   case "^" :
    return 3;
   case "e" :
    return 4;
   default :
    return 0;
  }
 }

 //求和函数
 private static function sum(mydata : Array) : Number {
  var s : Number = 0;
  for (var i in mydata) {
   s += mydata[i];
  }
  return s;
 }

 //求最小值
 private static function min(mydata : Array) : Number {
  var s : Number = mydata[0];
  for (var i in mydata) {
   if (mydata[i] < s) {
    s = mydata[i];
   }
  }
  return s;
 }

 //求最大值
 private static function max(mydata : Array) : Number {
  var s : Number = mydata[0];
  for (var i in mydata) {
   if (mydata[i] > s) {
    s = mydata[i];
   }
  }
  return s;
 }

 //判断操作数的类型(数字或变量)并作相应处理
 private static function _Number(str : String) : Number {
  if (str == "") {
   return 0;
  }
  var ch : String = str.substr(0, 1);
  if ((ch < "0" || ch > "9") && ch != "+" && ch != "-") {
   return eval(str);
  } else {
   return Number(str);
  }
 }

 //找出最里层的括号,并返回括号的起始位置及括号内的表达式
 private static function getInner(estr : String) : Object {
  var e : Number = estr.indexOf(")");
  var s : Number = estr.lastIndexOf("(", e);
  estr = estr.slice(s + 1, e);
  if (e != -1) {
   var obj : Object = {s:s, e:e, estr:estr};
   return obj;
  } else {
   return null;
  }
 }

 //计算带括号和函数的表达式
 private static function reckon2(estr : String) : Array {
  var i : Number, JHTEMP : Array, obj : Object, funcStr : String;
  
  obj = getInner(estr);
  while (obj != null) {
   JHTEMP = reckon1(obj.estr);
   //检查左括号的外边是否是一个函数名
   funcStr = null;
   for (i in farr) {
    var fIndex : Number = estr.lastIndexOf(farr[i], obj.s);
    if (fIndex != -1 && fIndex == obj.s - farr[i].length) {
     funcStr = farr[i];
     break;
    }
   }
   if (funcStr != null) {
    JHTEMP[0] = func(funcStr, JHTEMP);
    //JHTEMP[0] = Math.round(Number(JHTEMP[0])*10000000)/10000000;//取消可能出现的科学计数法,如1.5e-7
    estr = estr.slice(0, obj.s - funcStr.length) + JHTEMP[0] + estr.slice(obj.e + 1);
   } else {
    //JHTEMP[0] = Math.round(Number(JHTEMP[0])*10000000)/10000000;
    estr = estr.slice(0, obj.s) + JHTEMP[0] + estr.slice(obj.e + 1);
   }
   trace(estr);
   obj = getInner(estr);
  }
  var eArr : Array = reckon1(estr);
  return eArr;
 }

 //计算无括号带逗号表达式 9,1+1,7*2
 private static function reckon1(estr : String) : Array {
  var i : Number, eArr : Array = estr.split(",");
  for (i in eArr) {
   eArr[i] = reckon0(eArr[i]);
  }
  return eArr;
 }

 //计算无括号无逗号表达式 1+1/2
 private static function reckon0(estr : String) : Number {
  var i : Number, maxisp : Number, eArr : Array = toArray0(estr);
  //搜索数组,找出最高的优先级(非运算符的优先级为0)
  while (eArr.length > 1) {
   maxisp = 0;
   for (i in eArr) {
    maxisp = Math.max(maxisp, isp(eArr[i]));
   }
   //从左往右搜索优先级最高的第一个运算符并计算
   for (i = 0;i < eArr.length; i++) {
    if (maxisp > 0 && isp(eArr[i]) == maxisp) {
     var va : Array = [eArr[i - 1], eArr[i + 1]];
     eArr.splice(i - 1, 3, func(eArr[i], va));
     break;
    }
   }
  }
  return _Number(eArr[0]);
 }

 //分解无括号无逗号表达式字串
 private static function toArray0(estr : String) : Array {
  var index : Array = [], i : Number, temp : Number;
  //将正负号变为加减号
  if (estr.substr(0, 1) == "-" || estr.substr(0, 1) == "+") {
   estr = "0" + estr;
  }
  //搜索表达式字串中的所有运算符并记录其位置和长度
  for (i in oarr) {
   temp = -1;
   while ((temp = estr.indexOf(oarr[i], temp + 1)) != -1) {
    //如果不是"+-"或者"+-"的前一个字符不属于运算符
    if (oarr[i] != "+" && oarr[i] != "-" || temp != 0 && ostr.indexOf(estr.substr(temp - 1, 1)) == -1) {
     index.push([temp, oarr[i].length]);
          //否则表示当前检测到的是"+-",且代表的是正负号
    }
   }
  }
  
  index.sort(compareFunction);
  var _temp : String = estr;
  var s : Number = 0, e : Number;
  var eArr : Array = [];
  //将字串分解为元素并按顺序存储到数组里
  for (i = 0;i < index.length; i++) {
   e = index[i][0];
   eArr.push(_temp.slice(s, e));
   s = e + index[i][1];
   eArr.push(_temp.slice(e, s));
  }
  eArr.push(_temp.slice(s));
  return eArr;
 }

 private static function compareFunction(A, B) : Number {
  return A[0] > B[0] ? 1 : A[0] < B[0] ? -1 : 0;
 }
}

0

评论Comments