计算字符串表达式的函数(AS版)

先废话几句:AS中的计算误差也真是很有趣,例如:6.4-6.3=0.100000000000001,这是在Flash 8中运行的结果,我真是无语了!附图一张:

evalString 函数介绍:
evalString(expression:String) : Number

expression 为一个算术表达式,该函数将计算此表达式的值,并返回计算结果。此表达式仅限于简单的+、-、×、÷以及带括号的运算,表达式中不得有其他符号,包括空格。表达式中的数字不仅限于一位整数,也可为多位整数,甚至是小数

参数
expression:String – 一个字符串表达式。

返回
Number – 一个数值。

示例

var infix:String = “(48-20*(6.2-5))/(18-15)”;
trace(evalString(infix)); //output 8

函数算法思想

算法思想和上一篇《把中缀表达式转化为后缀表达式》中所表述的思想基本一致,只是在扫描数据以及运算符退栈时处理方法不同。

在扫描字符串时,若是数字,则加到一个字符串后面,同时扫描下一个字符,若不是数字字符也不是小数点,则把当前字符串转换为数字压入数字栈。

在遇到运算符需要退栈时,从数字栈中取出栈顶的两个数字,和退栈运算符一起进行运算,并把计算结果压入数字栈中,依次循环,直到无须退栈。扫描完成后,退栈运算符,并依次和数字栈中栈顶的数字进行运算,直至运算符栈为空。

函数代码如下:

/********************************************/
/* Calculate the value of a string */
/* Example: */
/* var infix:String = “(12.2-6.2)/(8-5)”; */
/* trace(evalString(infix)); //output 2 */
/********************************************/
/* Please keep this info when you quote */
/* www.afdream.com */
/* Author:Fdream */
/* Fdream All Rights Reserved */
/********************************************/

function evalString(infix:String) {
var opArray:Array = new Array();

//栈底标记
opArray[0] = ‘@’;
var op:Number = 1;
var postfix:Array = new Array();
var post:Number = 0;

//保存计算结果
var res:Number = 0;

var i, j;
var tempString:String = new String();

//计算两个数
function Caculate(opSign:String) {
if (opSign == ‘+’) {
res = postfix[post-2]+postfix[post-1];
} else if (opSign == ‘-‘) {
res = postfix[post-2]-postfix[post-1];
} else if (opSign == ‘*’) {
res = postfix[post-2]*postfix[post-1];
} else if (opSign == ‘/’) {
if (!postfix[post-1]) {
trace(“Expression Error!”);
} else {
res = postfix[post-2]/postfix[post-1];
}
}
postfix[post-1] = 0;
postfix[post-2] = res;
post–;
}

//扫描中缀表达式
for (i=0; i switch (infix.charAt(i)) {
//左括号就直接入栈
case ‘(‘ :
opArray[op] = infix.charAt(i);
op++;
break;
//右括号则退栈计算,直到遇见一个左括号
case ‘)’ :
for (j=op-1; j>0; j–) {
if (opArray[j] != ‘(‘) {
Caculate(opArray[j]);
opArray[j] = ‘#’;
} else {
opArray[j] = ‘#’;
break;
}
}
op = j;
break;
case ‘*’ :
case ‘/’ :
//如果栈顶的运算符为*或/,则先退栈,再入栈,否则直接入栈
if (opArray[op-1] == ‘*’) {
op–;
Caculate(opArray[op]);
opArray[op] = ‘#’;
} else if (opArray[op-1] == ‘/’) {
op–;
Caculate(opArray[op]);
opArray[op] = ‘#’;
}
opArray[op] = infix.charAt(i);
op++;
break;
case ‘+’ :
case ‘-‘ :
//如果栈顶的运算符不是左括号也不是栈底,则先退栈计算,再入栈
if (opArray[op-1] != ‘(‘ && opArray[op-1] != ‘@’) {
op–;
Caculate(opArray[op]);
opArray[op] = ‘#’;
}
opArray[op] = infix.charAt(i);
op++;
break;
default :
//如果是数字字符或者小数点则转化为数字存入数组
//如果下一个字符是运算符则把当前数字存入数组
tempString += infix.charAt(i);
var temp:String = new String();
temp = infix.charAt(i+1);
if (temp != ‘.’ && (temp>’9′ || temp<'0')) {
postfix[post] = parseFloat(tempString);
post++;
tempString = “”;
}
//trace(postfix);
}
}

//扫描完成,全部退栈
for (j=op-1; j>0; j–) {
if (opArray[j] != ‘@’) {
Caculate(opArray[j]);
opArray[j] = ‘#’;
} else {
break;
}
}
//返回结果
return postfix[0];
}

 

5 comments on “计算字符串表达式的函数(AS版)”

  1. 那个是计算机的浮点数运算的问题吧
    2进制表示10进制会有误差的噢
    不修正就会这样的

  2. 我认为可以把大家经常用到的Math也给解释了,比如Math就不输入了,直接”sqrt(2)”就是对2开方 这样能支持更多运算

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据