思路如下:
用栈计算表达式的方法原理及步骤:
建立两个栈,一个是数据栈,一个是计算符号栈,以(6+2*5)/4为例
1 优先级
符号之间的优先级如下:
"(" , ")" -1
"+" , "-" 0
"*" , "/" 1
数值越大,则越优先,同级别的比较时 先出现的优先。
2 将"(",")"设为特殊运算符,即单目运算,两邻两个运算符则可对消。
3 计算条件
(1) 当前运算符不等于""(特殊结束符)
(2) 运算符栈里的运行算个数>=1时
(3) 出栈口的运算符优先级高于将要入栈的运算符时或者两者可对消时。
4 计算时,则将符号出栈参与计算,数值栈的出栈口前两位元素出栈参与计算,
计算结果值向数值栈压栈,并进行递归此操作。具体步骤如下:
(1) "(" 压入符号栈
(2) "6"压入数值栈
(3) "("与"+"比较优先级,认为"("比"+"优先级低,则不满足计算条件,将"+"压入符号栈.
(4) 将"2" 压入数值栈。
(5) 将"*"与"+"比较优先级,算得"+"优先级低于"*",则不满足计算条件,将"*"压入符号栈。
(6) 将 "5"压入数植栈。
(7) 将"*"与")"比较优先级,得出"*"比")"优先级要高。进行计算,将"*"出栈、"5"、"2"出栈,参与计算
(8) 将 2*5 =10的结果压入数值栈。
(9) (递归)比较 "+"与")"优先级,得出"+"比")"优先级要高。再进行计算,将"+"出栈、"10"、"6"出栈,参与计算。
(10) 将 6+10 =16的结果压入数值栈。
(11) (递归)比较 ")"与"("优先级,得出两者可以对消,将"("符号出栈,与")"对消,继续取下一个符号。
(12) 将"/"入符号栈。
(13) 将"4"入数值栈。
(14) 发现""算式结束符,则进行计算, 将 "/"、"4’、"16"出栈,参与计算。
(15) 将计算结果压入数值栈。
源码如下:
用栈计算表达式的方法原理及步骤:
建立两个栈,一个是数据栈,一个是计算符号栈,以(6+2*5)/4为例
1 优先级
符号之间的优先级如下:
"(" , ")" -1
"+" , "-" 0
"*" , "/" 1
数值越大,则越优先,同级别的比较时 先出现的优先。
2 将"(",")"设为特殊运算符,即单目运算,两邻两个运算符则可对消。
3 计算条件
(1) 当前运算符不等于""(特殊结束符)
(2) 运算符栈里的运行算个数>=1时
(3) 出栈口的运算符优先级高于将要入栈的运算符时或者两者可对消时。
4 计算时,则将符号出栈参与计算,数值栈的出栈口前两位元素出栈参与计算,
计算结果值向数值栈压栈,并进行递归此操作。具体步骤如下:
(1) "(" 压入符号栈
(2) "6"压入数值栈
(3) "("与"+"比较优先级,认为"("比"+"优先级低,则不满足计算条件,将"+"压入符号栈.
(4) 将"2" 压入数值栈。
(5) 将"*"与"+"比较优先级,算得"+"优先级低于"*",则不满足计算条件,将"*"压入符号栈。
(6) 将 "5"压入数植栈。
(7) 将"*"与")"比较优先级,得出"*"比")"优先级要高。进行计算,将"*"出栈、"5"、"2"出栈,参与计算
(8) 将 2*5 =10的结果压入数值栈。
(9) (递归)比较 "+"与")"优先级,得出"+"比")"优先级要高。再进行计算,将"+"出栈、"10"、"6"出栈,参与计算。
(10) 将 6+10 =16的结果压入数值栈。
(11) (递归)比较 ")"与"("优先级,得出两者可以对消,将"("符号出栈,与")"对消,继续取下一个符号。
(12) 将"/"入符号栈。
(13) 将"4"入数值栈。
(14) 发现""算式结束符,则进行计算, 将 "/"、"4’、"16"出栈,参与计算。
(15) 将计算结果压入数值栈。
源码如下:
1
using System;
2
using System.Data;
3
using System.Configuration;
4
using System.Collections;
5
using System.Web;
6
using System.Web.Security;
7
using System.Web.UI;
8
using System.Web.UI.WebControls;
9
using System.Web.UI.WebControls.WebParts;
10
using System.Web.UI.HtmlControls;
11
12
public partial class Default2 : System.Web.UI.Page
13
{
14
//返回值
15
double result = 0.00;
16
//数值栈
17
Stack stNum = new Stack();
18
//符号栈
19
Stack stOptr = new Stack();
20
21
//ArrayList里对象转为字符串方便判断
22
string para;
23
//数值栈中倒数第二个值
24
string tempNum1;
25
//数值栈中倒数第一个值
26
string tempNum2;
27
//符号栈中倒数第一个值
28
string tempOptr;
29
//优先级对比返回值;
30
string cmpStr = "";
31
//临时计算结果
32
double tempResult = 0.00;
33
34
//按钮事件
35
protected void btnCal_Click(object sender, EventArgs e)
36
{
37
ArrayList al = GetExpression(this.tbxExpression.Text.Trim());
38
this.lbResult.Text = Calculate(al).ToString();
39
}
40
41
/// <summary>
42
/// 计算过程
43
/// </summary>
44
/// <param name="al">array表达式</param>
45
/// <returns></returns>
46
public double Calculate(ArrayList al)
47
{
48
49
for (int i = 0; i < al.Count; i++)
50
{
51
/* 要运算必须符号以下条件:
52
* (1)数值栈有两个或两个以上的值
53
* (2)符号栈中有一个或一个以上的值
54
* (3)并且当前值是符号或者是ArrayList最后一项(后者情况放最后处理)
55
* 具体步骤:
56
* step1:如果当前值是符号,对比优先级别后可以判断是否计算,如可以计算跳至step3
57
* step2:如果当前值是ArrayList最后一项,则跳至step3
58
* step3:提取数值栈中最后两个值,符号栈中最后一个值进行计算(当然符号栈中运算符不能为"("号或者为")"号) */
59
60
para = al[i].ToString();
61
//如果是最后一位且为数字,则压入栈
62
if (i == al.Count - 1 && !IsOptr(para))
63
{
64
stNum.Push(para);
65
}
66
67
if (stNum.Count > 1 && stOptr.Count > 0)
68
{
69
符合条件进行计算
106
}
107
else
108
{
109
插入栈
120
}
121
122
}
123
124
result = double.Parse(stNum.Peek().ToString());
125
return result;
126
}
127
128
//递归计算
129
private void CircleCal()
130
{
131
if (stNum.Count > 1 && stOptr.Count > 0 && IsOptr(para))
132
{
133
//弹出计算
134
tempNum2 = stNum.Pop().ToString();
135
tempNum1 = stNum.Pop().ToString();
136
tempOptr = stOptr.Pop().ToString();
137
138
//对比优先级
139
cmpStr = CmpPRI(tempOptr, para);
140
if (!string.IsNullOrEmpty(cmpStr))
141
{
142
//如果是等号说明是:"("号或")"号,单独处理而不计算
143
if ("=" == cmpStr)
144
{
145
//如果是匹配的一对左右括号,单目计算,符号对消掉
146
if (tempOptr == "(" && para == ")")
147
{
148
//不符合重新push回去,只把数值push回去,符号对消掉
149
stNum.Push(tempNum1);
150
stNum.Push(tempNum2);
151
para = "#";
152
CircleCal();
153
}
154
else
155
{
156
//不符合重新push回去
157
stNum.Push(tempNum1);
158
stNum.Push(tempNum2);
159
stOptr.Push(tempOptr);
160
//push入符号
161
stOptr.Push(para);
162
para = "#";
163
CircleCal();
164
}
165
}
166
else if (">" == cmpStr)
167
{
168
//真正符合条件进行计算
169
tempResult = CalNums(double.Parse(tempNum1), double.Parse(tempNum2), tempOptr);
170
//结果要push回数值栈去
171
stNum.Push(tempResult);
172
//递归计算
173
CircleCal();
174
}
175
else
176
{
177
//不符合重新push回去
178
stNum.Push(tempNum1);
179
stNum.Push(tempNum2);
180
stOptr.Push(tempOptr);
181
//push入符号
182
stOptr.Push(para);
183
para = "";
184
}
185
}
186
}
187
}
188
189
函数
380
381
}
382
using System;2
using System.Data;3
using System.Configuration;4
using System.Collections;5
using System.Web;6
using System.Web.Security;7
using System.Web.UI;8
using System.Web.UI.WebControls;9
using System.Web.UI.WebControls.WebParts;10
using System.Web.UI.HtmlControls;11

12
public partial class Default2 : System.Web.UI.Page13
{14
//返回值15
double result = 0.00;16
//数值栈17
Stack stNum = new Stack();18
//符号栈19
Stack stOptr = new Stack();20

21
//ArrayList里对象转为字符串方便判断22
string para;23
//数值栈中倒数第二个值24
string tempNum1;25
//数值栈中倒数第一个值26
string tempNum2;27
//符号栈中倒数第一个值28
string tempOptr;29
//优先级对比返回值;30
string cmpStr = "";31
//临时计算结果32
double tempResult = 0.00;33

34
//按钮事件35
protected void btnCal_Click(object sender, EventArgs e)36
{37
ArrayList al = GetExpression(this.tbxExpression.Text.Trim());38
this.lbResult.Text = Calculate(al).ToString();39
}40

41
/// <summary>42
/// 计算过程43
/// </summary>44
/// <param name="al">array表达式</param>45
/// <returns></returns>46
public double Calculate(ArrayList al)47
{48

49
for (int i = 0; i < al.Count; i++)50
{ 51
/* 要运算必须符号以下条件:52
* (1)数值栈有两个或两个以上的值53
* (2)符号栈中有一个或一个以上的值54
* (3)并且当前值是符号或者是ArrayList最后一项(后者情况放最后处理)55
* 具体步骤:56
* step1:如果当前值是符号,对比优先级别后可以判断是否计算,如可以计算跳至step357
* step2:如果当前值是ArrayList最后一项,则跳至step358
* step3:提取数值栈中最后两个值,符号栈中最后一个值进行计算(当然符号栈中运算符不能为"("号或者为")"号) */59
60
para = al[i].ToString();61
//如果是最后一位且为数字,则压入栈62
if (i == al.Count - 1 && !IsOptr(para))63
{64
stNum.Push(para);65
}66

67
if (stNum.Count > 1 && stOptr.Count > 0)68
{69
符合条件进行计算106
}107
else108
{109
插入栈120
}121

122
}123

124
result = double.Parse(stNum.Peek().ToString());125
return result;126
}127

128
//递归计算129
private void CircleCal()130
{131
if (stNum.Count > 1 && stOptr.Count > 0 && IsOptr(para))132
{133
//弹出计算134
tempNum2 = stNum.Pop().ToString();135
tempNum1 = stNum.Pop().ToString();136
tempOptr = stOptr.Pop().ToString();137

138
//对比优先级139
cmpStr = CmpPRI(tempOptr, para);140
if (!string.IsNullOrEmpty(cmpStr))141
{142
//如果是等号说明是:"("号或")"号,单独处理而不计算143
if ("=" == cmpStr)144
{145
//如果是匹配的一对左右括号,单目计算,符号对消掉 146
if (tempOptr == "(" && para == ")")147
{148
//不符合重新push回去,只把数值push回去,符号对消掉149
stNum.Push(tempNum1);150
stNum.Push(tempNum2);151
para = "#";152
CircleCal();153
}154
else155
{156
//不符合重新push回去157
stNum.Push(tempNum1);158
stNum.Push(tempNum2);159
stOptr.Push(tempOptr);160
//push入符号161
stOptr.Push(para);162
para = "#";163
CircleCal();164
}165
}166
else if (">" == cmpStr)167
{168
//真正符合条件进行计算169
tempResult = CalNums(double.Parse(tempNum1), double.Parse(tempNum2), tempOptr);170
//结果要push回数值栈去171
stNum.Push(tempResult);172
//递归计算173
CircleCal();174
}175
else176
{177
//不符合重新push回去178
stNum.Push(tempNum1);179
stNum.Push(tempNum2);180
stOptr.Push(tempOptr);181
//push入符号182
stOptr.Push(para);183
para = "";184
}185
}186
}187
}188

189
函数380

381
}382



浙公网安备 33010602011771号