日期:2014-05-20  浏览次数:20617 次

求助高手们,帮一下小弟,谢谢啦
输入一个运算表达式    
如: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( "- ")){