2004/12/23 | 继续表达式求值——支持函数——欢迎测试
类别(Flash习作) | 评论(0) | 阅读(341) | 发表于 00:47
这次做的和上次那个方法不同,上次是将中缀表达式转换
为后缀表达式,再利用堆栈求值,所以对函数就不知道如何做了;
而这次用的方法则完全是按人脑的计算过程,从左到右,从内至外,
函数运算也实现了,而且参数个数也没有限制,添加也很方便
目前已添加的函数有
abs,round,sqrt,sin,cos,tan,acos,asin,atan,log,exp,sum,avg,count,max,min
另外,这个同样也是可以使用变量的,供测试的变量有m,n,y,x,
程序中所有变量都可用,但有些是不能做算术运算的^_^


//目前,为方便检测"-"是否为负号,运算符只能用单个字符的
var ostr = "+,-,*,/,%,^";
var fstr = "abs,round,sqrt,sin,cos,tan,acos,asin,atan,log,exp,sum,avg,count,max,min";
//运算符及函数的具体运算
function func(optr:String, va:Array) {
  if (typeof (va[0]) == "object") {
    for (var i in va[0]) {
      va[i] = getNum(va[0][i]);
    }
  } else {
    for (var i in va) {
      va[i] = getNum(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 "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
function isp(optr:String) {
  switch (optr) {
  case "+" :
  case "-" :
    return 1;
  case "*" :
  case "/" :
  case "%" :
    return 2;
  case "^" :
    return 3;
  default :
    return 0;
  }
}
//求和函数
function sum(mydata:Array) {
  var s = 0;
  for (var i in mydata) {
    s += mydata[i];
  }
  return s;
}
//求最小值
function min(mydata:Array) {
  var s = mydata[0];
  for (var i in mydata) {
    if (mydata[i]<s) {
      s = mydata[i];
    }
  }
  return s;
}
//求最大值
function max(mydata:Array) {
  var s = mydata[0];
  for (var i in mydata) {
    if (mydata[i]>s) {
      s = mydata[i];
    }
  }
  return s;
}
//判断操作数的类型(数字或变量)并作相应处理
function getNum(str:String) {
  if (str == "") {
    return 0;
  }
  var ch = str.substr(0, 1);
  if ((ch<"0" || ch>"9") && ch != "-") {
    return eval(str);
  } else {
    return Number(str);
  }
}
//找出最里层的括号,并返回括号的起始位置及括号内的表达式
function godepth(estr) {
  var e = estr.indexOf(")");
  var s = estr.lastIndexOf("(", e);
  estr = estr.slice(s+1, e);
  if (e != -1) {
    var obj = {s:s, e:e, estr:estr};
    return obj;
  } else {
    return null;
  }
}
//计算带括号和函数的表达式
function toNum2(estr:String, ostr:String, fstr:String) {
  var i, JHTEMP, obj, funcStr, fArr;
  fArr = fstr.split(",");
  obj = godepth(estr);
  while (obj != null) {
    JHTEMP = toNum1(obj.estr, ostr);
    //检查左括号的外边是否是一个函数名
    funcStr = null;
    for (i in fArr) {
      var fIndex = estr.lastIndexOf(fArr[i], obj.s);
      if (fIndex != -1 && fIndex == obj.s-fArr[i].length) {
        funcStr = fArr[i];
        break;
      }
    }
    if (funcStr != null) {
      JHTEMP = func(funcStr, JHTEMP);
      estr = estr.slice(0, obj.s-funcStr.length)+JHTEMP+estr.slice(obj.e+1);
    } else {
      estr = estr.slice(0, obj.s)+JHTEMP[0]+estr.slice(obj.e+1);
    }
    trace(estr);
    obj = godepth(estr);
  }
  estr = toNum1(estr, ostr);
  return estr;
}
//计算无括号带逗号表达式
function toNum1(estr, ostr) {
  var i, eArr = estr.split(",");
  for (i in eArr) {
    eArr[i] = toNum0(eArr[i], ostr);
  }
  return eArr;
}
//计算无括号无逗号表达式
function toNum0(estr:String, ostr:String) {
  var i, maxisp, eArr = toArray0(estr, ostr);
  //搜索数组,找出最高的优先级(非运算符的优先级为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 = [eArr[i-1], eArr[i+1]];
        eArr.splice(i-1, 3, func(eArr[i], va));
        break;
      }
    }
  }
  return getNum(eArr[0]);
}
//分解无括号无逗号表达式字串
function toArray0(estr:String, ostr:String) {
  var oArr = ostr.split(",");
  var index = [], i, temp, newstr = "";
  //将负号变为减号
  if (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] != "-" || temp != 0 && ostr.indexOf(estr.substr(temp-1, 1)) == -1) {
        var L = index.length;
        index[L] = [];
        index[L][0] = temp;
        index[L][1] = oArr[i].length;
        //否则表示当前检测到的是"-",且代表的是负号
      }
    }
  }
  function compareFunction(A, B) {
    return A[0]>B[0] ? 1 : A[0]<B[0] ? -1 : 0;
  }
  index.sort(compareFunction);
  temp = estr;
  var s = 0, e;
  eArr = [];
  //将字串分解为元素并按顺序存储到数组里
  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;
}
//=============测试============
var z = [9, 7, -8, 6, 5, -2];
var m = -20;
var n = 4;
var x = 100;
var y = 3;
var estr = "sum(z)";
var TF = new TextFormat();
TF.align = "center";
this.createTextField("hello", 1, 0, 25, 400, 20);
with (hello) {
  type = "dynamic";
  selectable = false;
  setNewTextFormat(TF);
  text = "输入表达式后按ENTER开始计算";
}
this.createTextField("in_out", 2, 2, 50, 396, 20);
with (in_out) {
  type = "input";
  border = true;
  restrict = "A-Za-z0-9+*_/%()=.,\\-\\^";
  setNewTextFormat(TF);
  in_out.text = estr+"="+toNum2(estr, ostr, fstr);
}
function out() {
  var estr = in_out.text;
  var e = estr.lastIndexOf("=");
  if (e == -1) {
    e = estr.length;
  }
  estr = estr.slice(0, e);
  in_out.text = estr+"="+toNum2(estr, ostr, fstr);
}
var myListener = new Object();
Key.addListener(myListener);
myListener.onKeyDown = function() {
  if (Key.isDown(Key.ENTER)) {
    out();
  }
};
new _jh7086();
0

评论Comments