在网上看资料的时候,无意看到一道关于Java的题:
原意应该是随意输入一个合法的表达式,怎样用Java编写一个程序计算此表达式的值,
开始的时候觉得很简单,不就是+,-,*,/和括号吗?觉得应该很轻松就可以把此程序搞定,可是后来仔细一分析,总觉得如果自己解析,利用String提供的方法,似乎很难把"("解析出来,但是如果此表达式有很多很多括号呢?怎样用程序判断那些括号是一对?百思不得其解...我也知道如果用正则式也许会有解决的方法,但一直都只用过简单的正则式,没有深入理解过,就反而更难了.
后面才在网上找了一个高手写的正则式java程序,我感觉非常不错,精简,且运行效果理想,看来真应该好好学学正则式..
package com.color.io;
import java.util.regex.*;
import java.util.*;
/**
*利用正则式计算表达式的值
*@author: Eastsun
*@version: 0.5 07.2.26
*/
public class Calculate{
public static final String NUM_PATTERN = //数字的匹配模式
"(?:(?<=[//+//-//*//(/]|^)[+-]|)" //前缀判断,判断前面的+-是否为符号
+"(?:" //数字及小数点部分, 0. 以及 .0 都是合法的数字
+"(?://d*//.)?//d+|" //.0 的情形
+"/d+(?:/./d*)?" //0. 的情形
+")"
+"(?!//d|//.)"; //边界条件
public static final String BRA_PATTERN =
"/((NUM)/)".replace("NUM",NUM_PATTERN);
public static final String ADD_PATTERN =
"(NUM)//+(NUM)".replace("NUM",NUM_PATTERN);
public static final String SUB_PATTERN =
"(NUM)-(NUM)".replace("NUM",NUM_PATTERN);
public static final String MUL_PATTERN =
"(NUM)//*(NUM)".replace("NUM",NUM_PATTERN);
public static final String DIV_PATTERN =
"(NUM)/(NUM)".replace("NUM",NUM_PATTERN);
public static final Pattern BRA =Pattern.compile(BRA_PATTERN);
public static final Pattern ADD_OR_SUB =Pattern.compile("(?<=[^//+//-//*/]|^)(?:"+ADD_PATTERN+"|"+SUB_PATTERN+")(?=[^//*/]|$)");
public static final Pattern MUL_OR_DIV =Pattern.compile("(?<![//*/])(?:"+MUL_PATTERN+"|"+DIV_PATTERN+")");
private static double operator(Matcher m,int index){
index =index*2;
double a,b;
if(m.group(1)!=null){
a =Double.parseDouble(m.group(1));
b =Double.parseDouble(m.group(2));
}
else{
index ++;
a =Double.parseDouble(m.group(3));
b =Double.parseDouble(m.group(4));
}
double r =0.0;
switch(index){
case 0:
r =a+b;
break;
case 1:
r =a-b;
break;
case 2:
r =a*b;
break;
case 3:
r =a/b;
break;
}
return r;
}
public static double eval(String str){
StringBuilder sb =new StringBuilder(str.replaceAll("/s+",""));
while(true){
Matcher m =BRA.matcher(sb);
if(m.find()){
sb.replace(m.start(),m.end(),m.group(1));
}
else{
int index =1;
m =MUL_OR_DIV.matcher(sb);
if(!m.find()){
index --;
m =ADD_OR_SUB.matcher(sb);
if(!m.find()) break;
}
sb.replace(m.start(),m.end(),""+operator(m,index));
}
}
return Double.parseDouble(sb.toString());
}
public static void main(String[] args){
Scanner scan =new Scanner(System.in);
while(true){
System.out.print("/nEnter a expression :");
String str =scan.next();
if(str.equals("exit")) break;
System.out.print(str +" = "+eval(str));
}
}
}
方法二:
这个的正则表达式没有括号在里边。
package test;
import java.util.Stack;
public class Arithmetic1 {
static String[] operater = new String[20];
static String[] number = new String[20];
public int countExpression(String str) {
Stack countStack1 = new Stack();
Stack countStack2 = new Stack();
int result = 0;
number = str.split("///|//*|//+|//-");
operater = str.split("//d+");
for (int i = 0; i < number.length; i++) {
countStack1.push(number[i]);
if (i != number.length - 1) {
countStack1.push(operater[i + 1]);
}
}
while (!countStack1.isEmpty())
countStack2.push(countStack1.pop());
String op;
while (!countStack2.isEmpty()) {
result = 0;
op = countStack2.pop().toString();
if (op.equals("*")) {
result = Integer.parseInt(countStack1.pop().toString())
* Integer.parseInt(countStack2.pop().toString());
countStack1.push(result);
continue;
}
if (op.equals("/")) {
result = Integer.parseInt(countStack1.pop().toString())
/ Integer.parseInt(countStack2.pop().toString());
countStack1.push(result);
continue;
}
countStack1.push(op);
}
while (!countStack1.isEmpty())
countStack2.push(countStack1.pop());
while (!countStack2.isEmpty()) {
result = 0;
op = countStack2.pop().toString();
if (op.equals("+")) {
result = Integer.parseInt(countStack1.pop().toString())
+ Integer.parseInt(countStack2.pop().toString());
countStack1.push(result);
continue;
}
if (op.equals("-")) {
result = Integer.parseInt(countStack1.pop().toString())
- Integer.parseInt(countStack2.pop().toString());
countStack1.push(result);
continue;
}
countStack1.push(op);
}
return result;
// System.out.println(result);
}
public static void main(String[] args) {
int num;
Arithmetic1 ct = new Arithmetic1();
num = ct.countExpression("222+2*6*7-112*2+5*2-6*7");
System.out.println(num);
}
}