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

/*
 * FormulaCalculator.java
 *
 * Created on 2007年9月18日, 上午11:40
 * @title 转化字符串表达式为数学公式并算出结果
 * @description 转化字符串表达式为数学公式并算出结果
 * 注意:为了区分负号,这边使用#代替减号
 * 使用方法:
 * 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;
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值