看一个示例:

a=253
b=18
c=29
d=56
e=(a*(b+c)-d)/2*(c+a)*(5*(c+d/b))
f=(e/(a-c)*(c-b+d)+30*d/(a-b))*(d/b*2-d/c)

  可不可以用一个程序来计算这式子呢?

这就是本程序的功能。

之前写了一个程序 来计算不含变量的任意四则运算式,比如25*(30/6-1)+10 等等。 http://blog.csdn.net/lingyb011/article/details/5468598

现在要在这基础上 加入变量的计算。给出程序,其中加了很多注释,帮读者理解。

代码如下:

  1 import java.util.Scanner;
2 import java.util.Stack;
3 import java.util.regex.Matcher;
4 import java.util.regex.Pattern;
5
6 /**
7 * 表达式解析器
8 * 计算由数字、运算符和括号组成的表达式的值,并能处理变量
9 * 为了处理简单,本解析器只支持一个字母的变量,不区分变量字母的大小写
10 * @author jasonling
11 *
12 */
13 public class Exp {
14
15 /**
16 * Main方法
17 */
18 public static void main(String[] args){
19 Scanner scan = new Scanner(System.in);
20 char[] chs ;
21 char ope;
22 int len,i,j;
23 boolean readOrNot = true; //是否读取下一个字符串,默认必须为true,否则下面会报错
24 float digit=0,digit2=0;
25 float[] vars = new float[26]; //用来存储变量的值
26
27 Stack<Float> staDig = new Stack<Float>(); //用来存数字
28 Stack<Character> staOpe = new Stack<Character>(); //用来存操作符
29 //往操作符栈中推入做为结束标志的‘#’
30 staOpe.push('#');
31 String exp = null,suffix=null;
32 while(true) { //一次读取一个表达式
33 if(readOrNot) exp = scan.nextLine().trim();
34 readOrNot = true;
35 if(exp.indexOf("==") > -1) {
36 System.out.println("对不起,本程序目前暂不支持'=='或布尔运算!");
37 continue;
38 }
39 //做一个判断,如果输入中有字母和数字或字母和字母的组合变量,则不往下执行
40 String regExp = "([a-zA-Z]*\\d+[a-zA-Z]+)|(\\d*[a-zA-Z]+\\d+)|([a-zA-Z]+[a-zA-Z]+)";
41 Pattern pattern = Pattern.compile(regExp);
42 Matcher matcher = pattern.matcher(exp);
43 if(matcher.find()) {
44 System.out.println("对不起,本程序只支持单个字母的变量!您的程序输入可能有误!");
45 continue;
46 }
47
48 chs = exp.toCharArray(); //化成char数组
49 boolean bo = true;
50 //判断是否含有字母
51 if(hasAlpha(chs)){
52 //有字母就先化成一般的不含字母的四则运算式
53 //先判断是不是赋值型的表达式
54 regExp = "^[a-zA-Z]\\s*=\\s*\\d+(.?\\d+)?$";
55
56 pattern = Pattern.compile(regExp);
57 matcher = pattern.matcher(exp);
58 if(matcher.find()){ //这是一个赋值表达式
59 bo = false;
60 regExp = "\\s*=\\s*";
61 pattern = Pattern.compile(regExp);
62 String[] ss = pattern.split(exp);
63 float f = Float.parseFloat(ss[1]);
64 vars[ss[0].toLowerCase().charAt(0)-'a'] = f;
65 staDig.push(f);
66 //System.out.println(vars[ss[0].toLowerCase().charAt(0)-'a']);
67 } else { //有字母的运算
68 regExp = "^[a-zA-Z]\\s*=\\.+";
69 pattern = Pattern.compile(regExp);
70 matcher = pattern.matcher(exp);
71 if(matcher.find()) {
72 readOrNot = false;
73 suffix = exp.substring(0,exp.indexOf("="));
74 exp = exp.substring(exp.indexOf("=")+1);
75 continue;
76 }
77 bo = true;
78 regExp = "[a-zA-Z]";
79 pattern = Pattern.compile(regExp);
80 matcher = pattern.matcher(exp);
81 while(matcher.find()){
82 exp = matcher.replaceFirst(""+vars[matcher.group(0).toLowerCase().charAt(0)-'a']);
83 //System.out.println(exp);
84 pattern = Pattern.compile(regExp);
85 matcher = pattern.matcher(exp);
86 }
87 chs = exp.toCharArray(); //化成char数组。
88 }
89 }
90 if(bo){ //到这的时候,式子中的字母都已被替换。赋值语句不会进来到这
91 len = chs.length;
92 for(i = 0; i < len; i ++) {
93 if(Character.isWhitespace(chs[i])) { //如果 是空格 的话,直接跳过
94 continue;
95 } else if(Character.isDigit(chs[i])) { //如果 是数字 的话:
96 digit = chs[i]-'0';
97 int tmp = -1; boolean b = false;//用来辅助读取小数点后的数据
98 while(i < len-1 && (Character.isDigit(chs[i+1])||chs[i+1]=='.')) {
99 if(i < len-1 && chs[i+1]=='.') {
100 i ++;
101 b = true;
102 } else {
103 digit = digit*10 + chs[++i]-'0';
104 }
105 if(b) tmp++;
106 }
107 for(j = 0; j < tmp; j ++) digit/=10;
108 //System.out.println(digit);
109 staDig.push(digit);
110 } else if(isMulOrDiv(chs[i])) { //读到的是乘除
111 ope = chs[i];
112 if(chs[i+1] != '(')
113 {
114 digit2 = chs[++i]-'0';
115 int tmp = -1; boolean b = false;//用来辅助读取小数点后的数据
116 while(i < len-1 && (Character.isDigit(chs[i+1])||chs[i+1]=='.')) {
117 if(i < len-1 && chs[i+1]=='.') {
118 i ++;
119 b = true;
120 } else {
121 digit2 = digit2*10 + chs[++i]-'0';
122 }
123 if(b) tmp++;
124 }
125 for(j = 0; j < tmp; j ++) digit2/=10;
126
127 digit = staDig.pop();
128 staDig.push(operate(digit,digit2,ope));
129 } else {
130 staOpe.push(chs[i]);
131 }
132 } else if(isPlusOrMinu(chs[i]) || isGuahao(chs[i])) {
133 //加减
134 if(isPlusOrMinu(chs[i]))
135 staOpe.push(chs[i]);
136 //括号
137 switch(chs[i])
138 {
139 case '(':
140 staOpe.push(chs[i]);
141 break;
142 case ')':
143 while(staOpe.peek() != '(') //说明括号里面的式子还没处理完
144 {
145 ope = staOpe.pop();
146 digit2 = staDig.pop();
147 digit = staDig.pop();
148 staDig.push(operate(digit,digit2,ope));
149 }
150 staOpe.pop();
151 if(isMulOrDiv(staOpe.peek())){
152 ope = staOpe.pop();
153 digit2 = staDig.pop();
154 digit = staDig.pop();
155 staDig.push(operate(digit,digit2,ope));
156 }
157 break;
158 }
159 }
160 }
161 }
162 //到这时,整个式子已经读取完了,检查栈,并做相应的处理
163 while(staOpe.peek() != '#')
164 {
165 ope = staOpe.pop();
166 digit2 = staDig.pop();
167 digit = staDig.pop();
168 staDig.push(operate(digit,digit2,ope));
169 }
170 float t = staDig.pop();
171 if(suffix != null){
172 exp = suffix + "=" + t;
173 suffix = null;
174 readOrNot = false;
175 } else {
176 System.out.println(Math.round(t*10)/10.0); //只取一位小数
177 }
178 }
179 }
180
181 /**
182 * 判断一个字符串里面是否有字母
183 * @param chs
184 * @return
185 */
186 private static boolean hasAlpha(char[] chs) {
187 int i,len = chs.length;
188 for(i = 0; i < len; i ++) {
189 if(Character.isAlphabetic(chs[i])) return true;
190 }
191 return false;
192 }
193 /**
194 * 用来判断是否是乘除运算
195 */
196 private static boolean isMulOrDiv(char ch)
197 {
198 if(ch == '*' || ch == '/') return true;
199 return false;
200 }
201 /**
202 * 用来判断是否是加减运算
203 */
204 private static boolean isPlusOrMinu(char ch)
205 {
206 if(ch == '-' || ch == '+') return true;
207 return false;
208 }
209 /**
210 * 用来判断是否是括号
211 */
212 private static boolean isGuahao(char ch)
213 {
214 if(ch == '(' || ch == ')') return true;
215 return false;
216 }
217 /**
218 * 用来做相应的加减乘除运算
219 * @param data,data2: 要做运算的两个数字
220 * @param ope: 要做的运算
221 */
222 private static float operate(float data,float data2,char ope)
223 {
224 switch(ope)
225 {
226 case '*':
227 return data * data2;
228 case '/':
229 return data / data2;
230 case '+':
231 return data + data2;
232 case '-':
233 return data - data2;
234 default:
235 return 0;
236 }
237 }
238 }

  结果如下:

253.0
18.0
29.0
56.0
2.147483647E8
30.7

  

posted on 2011-08-23 14:35  Jasonling  阅读(984)  评论(0编辑  收藏  举报