输入一个运算表达式
如:12+100*3-50/5
判断表达式的正确性,如果正确,并求值....
------解决方案--------------------
记得某高人说过可以丢入数据库求值
------解决方案--------------------
不知道java有没有eval这样功能的方法
------解决方案--------------------
这个东西用词法分析最好,不过我不太懂编译原理。。。。只好笨办法了。另外附送一个功能,处理括号。
import java.util.LinkedList;
import java.util.List;
/**
* 这个类用来包装一段仅包括数字,+-/*和小数点.的字符串。
* 由于正则式写的比较简单,所以不支持负号-,所有的-都被认为是减号。
* 该类在计算表达式的时候遵循的策略是先将高优先级的运算(*与/)计算完毕再进行+-运算。
* 比如 1+3+4*5+4/2,该类具体计算过程为
* 1、先分解表达式,存为两个list "134542 "和 "++*+/ ",并纪录高优先级运算符数量为2
* 2、在存运算符的list的size不为0的情况下,将高优先级的运算计算 即先算 4*5 ,然后再 4/2 ,把式子转成1+3+20+2
* 3、依次计算全部是+-运算的式子
*/
class Formula{
private List <Double> listNumbers; //这个list纪录所有的要计算的值
private List <String> listOperator; //这个list纪录所有的操作符
private int highOperateNum = 0; //这个值标记着当前还有多少高级别的操作符,将会优先计算这些运算符相关的式子。
Formula(String strOri){
//由于在计算过程中,在计算一个式子后,需要更新list,用LinkedList比较好。
listNumbers = new LinkedList <Double> ();
listOperator = new LinkedList <String> ();
this.formatOri(strOri);
}
/**
* @param strOri 目标字符串
* 这个方法用来将字符串分解,注意这里没有验证字符串的有效性。
* 如果要添加对符号的支持,请修改这个方法中的具体实现。
*/
private void formatOri(String strOri){
String[] numTemp;
String[] optTemp;
numTemp = strOri.split( "[\\+\\-\\*/] ") ; //根据+-*/号分解字符串,
for(int i=0 ; i <numTemp.length ; i++){
listNumbers.add(Double.valueOf(numTemp[i]));
}
optTemp = strOri.split( "[0-9\\.]+ ");//根据数字和小数点分解字符串
for(int i=1 ; i <optTemp.length ; i++){
listOperator.add(optTemp[i]);
if (optTemp[i].equals( "* ") || optTemp[i].equals( "/ ")){
this.highOperateNum++ ;
}
}
}
public static void main(String args[]){
Formula f = new Formula( "1*3+5+5*6/8-23+6+14+12*3-6*4 "); //3+5+3.75-23+6+14+36-24 =20.75
System.out.println(f.getValue());
}
public double getValue(){
int firstHigh=0 ; //这个参数用来临时存储找出来第一个高优先级操作符的索引值
while (this.listOperator.size() > 0 ){ //如果操作符列表还有值代表运算没有最终完成
if (this.highOperateNum> 0){ //如果高优先值运算符的数量不为0,就先根据高优先级运算符计算
firstHigh = this.listOperator.indexOf( "* "); //尝试寻找第一个*的index
firstHigh = (firstHigh==-1?this.listOperator.indexOf( "/ "):firstHigh) ;//防止只剩下除法
if (firstHigh == -1) return Double.NaN; //this.highOperateNum> 0时,firstHigh不应该为0
this.perpareReckon(firstHigh); //尝试计算
}else{
this.reckon(0); //直接计算
}
}
return this.listNumbers.get(0).doubleValue();
}
/**
* @param index 表明要尝试计算的运算符位置.
* 该方法主要为了处理当前运算符为*,但是前面还有个/的及类似的情况(递归调用perpareReckon(index-1))
*/
private void perpareReckon(int index){
if (this.listOperator.get(index).equals( "* ")||this.listOperator.get(index).equals( "/ ")){
if (index> 0){
if (this.listOperator.get(index-1).equals( "+ ") || this.listOperator.get(index-1).equals( "- ")){