首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

高手们,帮一下小弟,多谢啦

2012-01-19 
求助高手们,帮一下小弟,谢谢啦输入一个运算表达式如:12+100*3-50/5判断表达式的正确性,如果正确,并求值...

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


this.reckon(index);
}
if( this.listOperator.get(index-1).equals( "* ") || this.listOperator.get(index-1).equals( "/ ")){
this.perpareReckon( index-1);
}
}else{
this.reckon(index);
}
}
}

/**
* @param optPos 运算符位置
* @return 运算结果
* 该方法根据运算位置,分别取出运算值和运算符位置进行计算
*/
private void reckon(int optPos){

double temp=0 ;
if (this.listOperator.get(optPos).equals( "* ")){
temp = this.listNumbers.get(optPos).doubleValue() * this.listNumbers.get(optPos+1).doubleValue();
System.out.println(this.listNumbers.get(optPos).doubleValue()+ "* "+ this.listNumbers.get(optPos+1).doubleValue() + "= "+temp);
updateList(optPos , Double.valueOf(temp)) ;
this.highOperateNum--;
}else if (this.listOperator.get(optPos).equals( "/ ")){
temp = this.listNumbers.get(optPos).doubleValue() / this.listNumbers.get(optPos+1).doubleValue();
System.out.println(this.listNumbers.get(optPos).doubleValue()+ "/ "+ this.listNumbers.get(optPos+1).doubleValue() + "= "+temp);
updateList(optPos , Double.valueOf(temp)) ;
this.highOperateNum--;
}else if (this.listOperator.get(optPos).equals( "+ ")){
temp = this.listNumbers.get(optPos).doubleValue() + this.listNumbers.get(optPos+1).doubleValue();
System.out.println(this.listNumbers.get(optPos).doubleValue()+ "+ "+ this.listNumbers.get(optPos+1).doubleValue() + "= "+temp);
updateList(optPos , Double.valueOf(temp)) ;
}else if (this.listOperator.get(optPos).equals( "- ")){
temp = this.listNumbers.get(optPos).doubleValue() - this.listNumbers.get(optPos+1).doubleValue();
System.out.println(this.listNumbers.get(optPos).doubleValue()+ "- "+ this.listNumbers.get(optPos+1).doubleValue() + "= "+temp);
updateList(optPos , Double.valueOf(temp)) ;
}else{
System.out.println( "ERROR!!!! ");
}
}

/**
* @param index 要在list中删除的值的index,以及
* @param value 要新添加的值
* 该方法用来在进行一次计算后,更新list.
*/
private void updateList(int index , Double value){
this.listNumbers.remove(index+1);
this.listNumbers.remove(index);
this.listNumbers.add(index,value);
this.listOperator.remove(index);
}

public void cls(){
this.highOperateNum = 0 ;
this.listNumbers.clear();
this.listOperator.clear();
}
}


/**
* 这个类在Formula的基础上添加了处理括号的能力。该类会把每个带括号的式子进行分解,
* 每个括号的内容作为一个Formula实例来计算结果,并将结果合并到上一级的括号内。 *
*/
public class FormulaS {

FormulaS(){}

/**
* @param str
* @return
* 该类用来验证字符串格式。当前没有验证。直接返回true
*/
private boolean validate(String str){return true;}

public double getValue(String strOri){

if (!this.validate(strOri)) return Double.NaN ;

int prev = -1 ;
int next = -1 ;

while ((prev=strOri.lastIndexOf( '( ')) != -1){

StringBuffer sb = new StringBuffer();
sb.append(strOri.substring(0, prev));


Formula f = new Formula(strOri.substring(prev+1, (next=strOri.indexOf( ') '))));
sb.append(f.getValue());
sb.append(strOri.substring(next+1));
f.cls();
System.out.println( "完成一个括号内部的计算 ");
strOri = sb.toString() ;
}

return new Formula(strOri).getValue();
}

public static void main(String[] args) {

String str = "3+3-3*3/3*(2+2-2*2/2*(4+4-4*4/4)+5+5)+10+20-10 " ;
//第一次计算后的结果 "3+3-3*3/3*(2+2-2*2/2*4+5+5)+10+20-10 "
//第二次计算后的结果 "3+3-3*3/3*6+10+20-10 "

FormulaS fs = new FormulaS();
System.out.println( "最后的运算结果为: "+fs.getValue(str));
}
}

[解决办法]
太麻烦了,用栈就可以完全实现

热点排行
Bad Request.