日常学习中总是能遇到做计算器的时候。今天,我就简单介绍一下我想的表达式求值方法。(有括号的表达式可以通过这个思路延伸出来)
一、分析
数学表达式求值、计算器求值都是根据运算符优先级来进行相应计算的。
怎么处理符号的优先级是非常重要的。
我以前学过用栈来求解表达式,但是需要个复杂的运算符优先级数组,这个数组很难记忆,不方便使用。
但优先级大小完全可以用数值大小来表示,数值也能有优先级。
二、解决办法
优先级处理:
1、将 *、/ 、%运算符优先级定义为3。(括号优先级可以定为4)
2、将 +、- 运算符优先级定义为2。
3、将数值(1、2.5这种)优先级定义为1。
4、= 号优先级可有可无,想用就设为0。
数值处理
1、0-9正常大小
2、“+”大小为10,“-”大小为11,“*”大小为12,“/”大小为13,“%”大小为14
用两个数组保存主要数据,一切操作围绕数组进行。
通过代码注释讲解
String function(String str){//按下等号
int lg = str.length; //得到字符串长度
String ms = str; //复制字符串
float ary[20]; //保存数值,(=-*/%)对应(10、11、12、13、14)
float ary2[20]; //保存优先级 ,3、2、1、0
float s = 0.0; //储存结果
int i = 0,j = 0;
int t = 0; //表示数值个数,ary数组已使用空间大小
int flag = 0; //
float num = 0.0; //字符串转浮点数要用
String temp = ""; //存储得到的数值字符串
int max = 0; //比较优先级
int mf = 0;
int left = 0;
int right = 0;
//遍历字符串,将字符串信息提取为数值数组和优先级数组
for(i = 0;i < lg;i++) {
//如果到达字符串结尾,保存最后一位数到ary数组中
if(i==(lg-1)){
temp = ms.substring(flag,lg); //得到对应的数值字符串
num = parseFloat(temp); //字符串转浮点数
ary[t] = num; //对应位赋值
ary2[t] = 1; //优先级为1
t++;
}
//如果检测到是运算符,得到运算符之前的数并保存,然后保存运算符及其优先级
if(ms.charAt(i)=="+" || ms.charAt(i)=="-" || ms.charAt(i)=="*" || ms.charAt(i)=="÷" || ms.charAt(i)=="%"){
temp = ms.substring(flag,i); //得到对应的数值字符串
num = parseFloat(temp); //字符串转浮点数
ary[t] = num; //对应位赋值
ary2[t] = 1;
t++;
switch(ms.charAt(i)){
case "+":
ary[t] = 10; //加号大小定义为10,优先级是2
ary2[t] = 2;
break;
case "-":
ary[t] = 11;
ary2[t] = 2;
break;
case "*":
ary[t] = 12; //乘号大小定义为12,优先级为3,其他类似
ary2[t] = 3;
break;
case "÷":
ary[t] = 13;
ary2[t] = 3;
break;
case "%":
ary[t] = 14;
ary2[t] = 3;
break;
}
flag = i+1; //标记运算符在的位,方便之后得到数
t++;
}
}
//上面得到了二个数组
//例子:2+3.2*7
//ary: 2 10 3.2 12 7
//ary2: 1 2 1 3 1
//根据两个数组处理字符串
//*********************************************************
//找出最高优先级的操作,再找出左右最近的两个操作数(优先级为1)
//执行该运算操作
//将结果赋值到左操作数上,其他位对应的优先级置0
//循环该过程,直到最高优先级为1时结束
//此时,表达式只剩下了结果保存在ary[0]中
//********************************************************
for(i = 0;i < t;i++){
max = 0;
for(j = 0;j < t;j++){
if(ary2[j]>max){
max = ary2[j];
//left:左操作数下标,right:右操作数下标,mf运算符下标
left = right = mf = j;
}
}
if(max == 1){
//结束标志
return str + "=" + s;
}
while(ary2[left]!=1){ //得到左操作数
left--;
}
while(ary2[right]!=1){//d得到右操作数
right++;
}
//执行运算符操作
switch(ary[mf]){
case 10:
s = ary[left] + ary[right] ;
break;
case 11:
console.log(11);
s = ary[left] - ary[right];
break;
case 12:
console.log(12);
s = ary[left] * ary[right];
break;
case 13:
console.log(13);
s = ary[left] / ary[right];
break;
case 14:
console.log(14);
s = ary[left] % ary[right];
break;
}
ary[left]=s; //将结果保存在左操作数位置上
for(int k = left+1;k <= right;k++){
ary2[k] = 0; //将运算符及右操作数优先级置0
}
}
}
}
//例子:2+3.2*7 ,两个数组最后的值
//ary: 24.4 10 22.4 12 7
//ary2: 1 0 0 0 0
这个算法我就用了2个数组就解决了,今天能想到这个方法,有点小高兴!!