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

来源:互联网 发布:软件壳种类 编辑:程序博客网 时间:2024/04/26 18:46

/*
 * 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;
    }

}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 怀孕四个月胎盘低置怎么办 孕37周胎盘三级怎么办 孕37周胎盘老化怎么办 怀孕22周胎盘1级怎么办 婴儿吃奶粉吐奶怎么办 宝宝吐奶又拉稀怎么办 羊水穿刺21三体怎么办 开始长妊娠纹了怎么办 已经长了妊娠纹怎么办 孕晚期长妊娠纹怎么办 妊娠纹长出来了怎么办 没提前预约四维怎么办 ct检查冠脉钙化怎么办 残角子宫有内膜怎么办 怀孕了长痔疮了怎么办 人流后子宫内膜薄怎么办 多囊子宫内膜薄怎么办 6岁儿童不爱睡觉怎么办 初生儿嗓子哑了怎么办 6岁儿童睡眠不好怎么办 8岁儿童睡眠不好怎么办 1个月婴儿睡眠少怎么办 三岁宝宝心跳快怎么办 宝宝右心房稍大怎么办 胎儿右心房偏大怎么办 胎心监测波动小怎么办 怀孕6个月不想要了怎么办 高敏肌钙蛋白t高怎么办 龟头沟槽里长疙瘩怎么办 肝郁气滞的体质怎么办 手指甲长在肉里怎么办 甲床与指甲脱离怎么办 指甲往肉里面长怎么办 指甲和肉分离是怎么办 大脚趾指甲空了怎么办 脚趾甲长在肉里怎么办 脚趾甲又厚又硬怎么办 小孩子咳嗽有痰怎么办%3f 支气扩张咳血怎么办小 背部第8块脊椎疼怎么办 坐时间长了背疼怎么办