您的位置:首页 > 其它

转化字符串表达式为数学公式并算出结果—实用类

2010-11-22 21:42 429 查看
/*
* FormulaCalculator calculator=new FormulaCalculator();
* calculator.getResult("10.23#20.67*(5.12+7.82)/2",2);
* v1.0.0 created by chenfc
*
*/

package org.jceun;

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FormulaCalculator ... {
private boolean isRightFormat = true ;
public String DIVISOR_EQUALS_ZERO = " 0.0 " ; // 除数为零时的返回值
/** */ /**
* 为了区分负号,这边使用#代替减号
* @param formula 字符串表达式
* @return 返回公式计算结果
*/
public double getResult(String formula) ... {
double returnValue = 0 ;
try ... {
returnValue = doAnalysis(formula);
} catch (NumberFormatException nfe) ... {
System.out.println( " 公式格式有误,请检查: " + formula);
} catch (Exception e) ... {
e.printStackTrace();
}
if ( ! isRightFormat) ... {
System.out.println( " 公式格式有误,请检查: " + formula);
}
return returnValue;
}
/** */ /**
* 采用BigDecimal.ROUND_HALF_UP方式返回指定精度的运算结果
* @param formula 公式
* @param decimalPlace 要保留的小数位数
* @return 返回公式计算结果
*/
public String getResult(String formula, int decimalPlace) ... {
return getResult(formula,decimalPlace,BigDecimal.ROUND_HALF_UP);
}
/** */ /**
* 返回指定精度及舍去尾数的策略的运算结果
* @param formula 公式
* @param decimalPlace 要保留的小数位数
* @param roundMethod 舍去尾数的策略
* 可取值有BigDecimal.ROUND_HALF_UP BigDecimal.ROUND_HALF_DOWN祥见BigDecimal
* @return 返回公式计算结果
*/
public String getResult(String formula, int decimalPlace, int roundMethod) ... {
double result = getResult(formula);
if (result == Double.MAX_VALUE)
return DIVISOR_EQUALS_ZERO;
else
return numberAround(result,decimalPlace,roundMethod);
}
private double doAnalysis(String formula) ... {
double returnValue = 0 ;
LinkedList < Integer > stack = new LinkedList < Integer > ();

int curPos = 0 ;
String beforePart = "" ;
String afterPart = "" ;
String calculator = "" ;
isRightFormat = true ;
while (isRightFormat && (formula.indexOf( ' ( ' ) >= 0 || formula.indexOf( ' ) ' ) >= 0 )) ... {
curPos = 0 ;
for ( char s : formula.toCharArray()) ... {
if (s == ' ( ' ) ... {
stack.add(curPos);
} else if (s == ' ) ' ) ... {
if (stack.size() > 0 ) ... {
beforePart = formula.substring( 0 , stack.getLast());
afterPart = formula.substring(curPos + 1 );
calculator = formula.substring(stack.getLast() + 1 , curPos);
formula = beforePart + doCalculation(calculator) + afterPart;
stack.clear();
break ;
} else ... {
System.out.println( " 有未关闭的右括号! " );
isRightFormat = false ;
}
}
curPos ++ ;
}
if (stack.size() > 0 ) ... {
System.out.println( " 有未关闭的左括号! " );
break ;
}
}
if (isRightFormat) ... {
returnValue = doCalculation(formula);
}
return returnValue;
}
/** */ /**
* 为了区分负号,这边使用#代替减号
*/
private double doCalculation(String formula) ... {
ArrayList < Double > values = new ArrayList < Double > ();
ArrayList < String > operators = new ArrayList < String > ();
int curPos = 0 ;
int prePos = 0 ;
for ( char s : formula.toCharArray()) ... {
if (s == ' + ' || s == ' # ' || s == ' * ' || s == ' / ' ) ... {
values.add(Double.parseDouble(formula.substring(prePos, curPos)
.trim()));
operators.add( "" + s);
prePos = curPos + 1 ;
}
curPos ++ ;
}
values.add(Double.parseDouble(formula.substring(prePos).trim()));
char op;
for (curPos = operators.size() - 1 ; curPos >= 0 ; curPos -- ) ... {
op = operators.get(curPos).charAt( 0 );
switch (op) ... {
case ' * ' :
values.add(curPos, values.get(curPos) * values.get(curPos + 1 ));
values.remove(curPos + 1 );
values.remove(curPos + 1 );
operators.remove(curPos);
break ;
case ' / ' :
if (values.get(curPos + 1 ).doubleValue() == 0.0 ) // 除数为零时
values.add(curPos, new Double(getDefaultValue()));
else
values.add(curPos, values.get(curPos) / values.get(curPos + 1 ));
values.remove(curPos + 1 );
values.remove(curPos + 1 );
operators.remove(curPos);
break ;
}
}
for (curPos = operators.size() - 1 ; curPos >= 0 ; curPos -- ) ... {
op = operators.get(curPos).charAt( 0 );
switch (op) ... {
case ' + ' :
values.add(curPos, values.get(curPos) + values.get(curPos + 1 ));
values.remove(curPos + 1 );
values.remove(curPos + 1 );
operators.remove(curPos);
break ;
case ' # ' :
values.add(curPos, values.get(curPos) - values.get(curPos + 1 ));
values.remove(curPos + 1 );
values.remove(curPos + 1 );
operators.remove(curPos);
break ;
}
}
return values.get( 0 ).doubleValue();
}
/** */ /**
* 对数字进行四舍五入
* @param dN 要四舍五入的数
* @param decimalPlace 精度
* @param roundMethod 舍去尾数的策略
* 可取值有BigDecimal.ROUND_HALF_UP BigDecimal.ROUND_HALF_DOWN祥见BigDecimal
*/
public String numberAround( double dN, int decimalPlace, int roundMethod) ... {
BigDecimal bd = new BigDecimal(String.valueOf(dN));
bd = bd.setScale(decimalPlace, roundMethod);
return String.valueOf(bd);
}
/** */ /**
* 对给定的字符串进行模式匹配
* @param str 要匹配的字符串
* @param regix 模式
* @return 返回匹配结果,成功为true,否则为false
* */
public boolean check(String str,String regix) ... {
boolean result = false ;
Pattern p = Pattern.compile(regix);
Matcher m = p.matcher(str);
result = m.matches();
return result;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: