您的位置:首页 > 移动开发 > Objective-C

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

2011-10-10 09:43 537 查看
 /*


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


    }


}

 

//:表达式解析-两栈算法.txt

//:Arithmetic.java

package   citi;

import   java.util.Iterator;

import   java.util.Stack;

import   java.util.ArrayList;

public   class   Arithmetic{

    //定义操作符,为简单起见,只涉及四则运算,可相应扩充之

    static   String   Operators= "+-*/()# ";

    //定义操作符的比较优先级,

    //其中1表示前面的操作符优于后面的操作符

    //       -1表示前面的操作符低于后面的操作符    

    //         0表示前面的操作符等于后面的操作符

    //         2表示前面的操作符不可能与后面的操作符相比较,如果碰到,则表达式有错    

    //PrecedeList[0][]表示+和+-*/()#这七个操作符相比较的优先级

    //PrecedeList[1][]表示-和+-*/()#这七个操作符相比较的优先级

    //以此类推

    static   byte   PrecedeList[][]={

                                                                {   1,   1,-1,-1,-1,   1,   1},

                                                                {   1,   1,-1,-1,-1,   1,   1},

                                                                {   1,   1,   1,   1,-1,   1,   1},

                                                                {   1,   1,   1,   1,-1,   1,   1},

                                                                {-1,-1,-1,-1,-1,   0,   2},

                                                                {   1,   1,   1,   1,   2,   1,   1},

                                                                {-1,-1,-1,-1,-1,   2,   0}};

    //定义数据中可能出现的数字和小数点,可以扩展

    static   String   Numbers= "0123456789. ";

    private   Stack   Operator,Operand;

    private   ArrayList   Expression;

   

    public   Arithmetic(String   inputStr){

    Operator=new   Stack();

    Operator.push( "# ");

    Operand=new   Stack();

    Expression=new   ArrayList();

    Parse(inputStr);

    }

    //解析输入的表达式,将操作符和数据分开

    //如输入表达式2+3*(32-2)则解析成2   +   3   *   (   32   -   2   )这九个字符串

    private   void   Parse(String   instr){

    String   single;    

    int   temp;

    String   tempstr= "# ";

    for(int   i=0;i <instr.length();i++){    

    single=instr.substring(i,i+1);

    //排除非操作符、数字的非法输入,如2+3m

    //Operators.indexOf(single)==6排除#

    if(Numbers.indexOf(single) <0   &&   (Operators.indexOf(single) <0   ||   Operators.indexOf(single)==6)){

    System.out.println( "Input   have   wrong   char: "+single);

    Expression.clear();

    return;

    }

    //获得前一个输入字符

    temp=Expression.size()-1;

    if(temp> -1){

    tempstr=(String)Expression.get(temp);

    }

    //排除连续两个操作符的情况,如3**2

    if(Operators.indexOf(single)> -1   &&   temp> -1   &&   Operators.indexOf(tempstr)> -1){

    System.out.println( "Input   have   wrong   format,two   Operators   are   conjoint ");

    Expression.clear();

    return;

    }    

    //如果当前字符是数字(包括.)而且前一字符也是数字,则将当前字符加到前一字符后面

    //其他情况均新添加一个元素

    if(Operators.indexOf(single) <0   &&   temp> -1   &&   Operators.indexOf(tempstr) <0){

    Expression.set(temp,tempstr+single);

    }    

    else{

        Expression.add(single);//其他情况均新添加一个元素

    }

    }    

    //为了算法处理方便起见,添加特殊字符#

    Expression.add( "# ");    

    }

   

    //比较两个操作符的优先级

    private   byte   Precede(String   firstOperator,String   secondOperator){

    return   PrecedeList[Operators.indexOf(firstOperator)][Operators.indexOf(secondOperator)];

    }    

   

    //对两个数据字符串进行运算

    private   double   Operate(String   firstOperand,String   Operator,String   secondOperand){

    if(Operator.equals( "+ ")){

    return   (Double.parseDouble(firstOperand)+Double.parseDouble(secondOperand));

    }

    else   if(Operator.equals( "- ")){

    return   (Double.parseDouble(firstOperand)-Double.parseDouble(secondOperand));

    }

    else   if(Operator.equals( "* ")){

    return   (Double.parseDouble(firstOperand)*Double.parseDouble(secondOperand));

    }

    else   if(Operator.equals( "/ ")){

    return   (Double.parseDouble(firstOperand)/Double.parseDouble(secondOperand));

    }

    else{

        System.out.println( "Operator   is   wrong!Can   throw   a   Exception ");

        return   0;

        }

    }

    //采用两个栈对接解析后的表达式进行运算

    public   double   Compute(){

    if(Expression.isEmpty()){

    System.out.println( "Expresion   is   empty ");

    return   0;

    }

    Iterator   it   =   Expression.iterator();

    String   single;

    String   firstOperand,secondOperand;

       

    single=(String)it.next();

    while(!(single.equals( "# ")   &&   Operator.peek().equals( "# "))){

    if(Operators.indexOf(single) <0){

    Operand.push(single);single=(String)it.next();

    }

    else{

        switch(Precede((String)Operator.peek(),single)){

        case   -1:Operator.push(single);single=(String)it.next();break;

        case   0:   Operator.pop();single=(String)it.next();break;

        case   1:  

                        secondOperand=(String)Operand.pop();

                        firstOperand=(String)Operand.pop();

                        Operand.push(String.valueOf(Operate(firstOperand,(String)Operator.pop(),secondOperand)));break;

        case   2:   System.out.println( "Expression   is   wrong!Can   throw   a   Exception ");break;

        }

        }

    }    

        return   Double.parseDouble((String)Operand.pop());

    }

   

    public   static   void   main(String[]   args){

    long   t1   =   System.currentTimeMillis();        

       

    Arithmetic   t=new   Arithmetic(args[0]);

    System.out.println(t.Compute());    

   

    long   t2   =   System.currentTimeMillis();

        System.out.println( "Time   needed:   "   +   (t2   -   t1));

    }

}

 

 

C# code

using System;
using System.Text;

namespace Lentro.Edu.Ch02
{
public class Expression
{
private StackSimple<int> theStack;
public StringBuilder suffix = new StringBuilder();

/**
* 检查该字符是否为括号
*/
private bool isParen(char c)
{
if (c == '{' || c == '[' || c == '(' || c == ')' || c == ']' || c == '}')
return true;
else
return false;
}

/**
* 检查是否为左括号
*/
private bool isLeftParen(char c)
{
if (c == '{' || c == '[' || c == '(')
return true;
else
return false;
}

/**
* 判断指定的操作符是否为 '+' 或者 '-'
*/
private bool isAddOrSub(int oper)
{
return oper == '+' || oper == '-';
}

/**
* 检查是否为数字
*/
private bool isNumber(int ch)
{
return ch >= 48 && ch <= 57;
}

/**
* 检查表达式是否合法
*/
private bool checkExp(String exp)
{
char[] ch = exp.ToCharArray();
StackSimple<int> theStackXInt = new StackSimple<int>(exp.Length / 2);

/**
* 遍历表达式,只处理括号部分
*/
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
if (isParen(c))
{
/**
* 左括号进栈
*/
if (isLeftParen(c))
{
theStackXInt.Push(c);
}
else
{
if (theStackXInt.IsEmpty())
{
return false;
}
int left = theStackXInt.Pop();
switch (c)
{
case '}':
if (left != '{')
return false;
break;
case ']':
if (left != '[')
return false;
break;
case ')':
if (left != '(')
return false;
break;
}
}
}
}
if (theStackXInt.IsEmpty())
{
return true;
}
else
{
return false;
}
}

/**
* 根据当前操作符处理之前在栈中的操作符,当前操作符暂不处理,放入栈中
*/
private void processOper(char oper)
{
while (!theStack.IsEmpty())
{
int currTop = theStack.Pop();
/**
* 如果是左括号,则不予处理,将括号返回进栈
*
* 若得到的操作符,则进一步判断
*/
if (currTop == '(')
{
theStack.Push(currTop);
break;
}
else
{
if (this.isAddOrSub(currTop))
{
if (this.isAddOrSub(oper))
{
this.suffix.Append((char)currTop);
}
else
{
this.theStack.Push(currTop);
break;
}
}
else
{
this.suffix.Append((char)currTop);
break;
}
}
}
/**
* 当前操作符进栈
*/
theStack.Push(oper);
}

/**
* 处理括弧.
*
* 如果为左括弧,直接进栈;
*
* 否则为右括弧,现将这一对括号中的操作符优先处理完
*/
private void processParen(char paren)
{
if (this.isLeftParen(paren))
{
this.theStack.Push(paren);
}
else
{
while (!theStack.IsEmpty())
{
int chx = theStack.Pop();
if (chx == '(')
break;
else
suffix.Append((char)chx);
}
}
}

/**
* 将正确的中缀表达式转为后缀表达式
*/
private void doTrans(String exp)
{
theStack = new StackSimple<int>(exp.Length);
if (this.checkExp(exp))
{
char[] ch = exp.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
switch (c)
{
case '+':
case '-':
case '*':
case '/':
this.processOper(c);
break;
case '(':
case ')':
this.processParen(c);
break;

default:
this.suffix.Append(c);
break;
}
}

while (!this.theStack.IsEmpty())
{
this.suffix.Append((char)this.theStack.Pop());
}
}
}

/**
* 计算表达式
*/
public int clac(String exp)
{
this.doTrans(exp);
String suff = this.suffix.ToString();
StackSimple<int> stack = new StackSimple<int>(suff.Length);

if (suff == null || suff.Length == 0)
{

}
else
{
char[] ch = suff.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
if (this.isNumber(c))
{
stack.Push(c - 48);
}
else
{
int operand2 = stack.Pop();
int operand1 = stack.Pop();
switch (c)
{
case '+':
stack.Push(operand1 + operand2);
break;
case '-':
stack.Push(operand1 - operand2);
break;
case '*':
stack.Push(operand1 * operand2);
break;
case '/':
stack.Push(operand1 / operand2);
break;
}
}
}
}
return stack.Peep();
}
}
}

其中StackSimple是自己写的一个简单的栈实现

C# code


using System;

namespace Lentro.Edu.Ch02
{
/// <summary>
/// 用于演示栈(LIFO)的内部实现机制
///
/// xfeng/2010-05-07
/// </summary>
public class StackSimple<T>
{
//栈默认的初始容量大小
private const int DEFAULT_SIZE = 10;

private T[] array;

private int index;

/// <summary>
/// 初始化 Stack 类的新实例,该实例为空并且具有默认初始容量。
/// </summary>
public StackSimple()
: this(DEFAULT_SIZE) { }

/// <summary>
/// 初始化 Stack 类的新实例,该实例为空并且具有指定的初始容量。
/// </summary>
/// <param name="size"></param>
public StackSimple(int size)
{
index = -1;
this.array = new T[size];
}

private int _count;
/// <summary>
/// 获取 Stack 中包含的元素数。
/// </summary>
public int Count
{
get { return _count; }
}

/// <summary>
/// 清空栈
/// </summary>
public void Clear()
{
for (int i = 0; i < array.Length; i++)
{
array[i] = default(T);
this.index = -1;
this._count = 0;
}
}

public Boolean IsEmpty()
{
return this._count == 0;
}

/// <summary>
/// 返回位于 Stack 顶部的对象但不将其移除。
/// </summary>
/// <returns>位于 Stack 顶部的 Object。</returns>
public T Peep()
{
return this.index < 0 ? default(T) : this.array[this.index];
}

/// <summary>
/// 移除并返回位于 Stack 顶部的对象。
/// </summary>
/// <returns>从 Stack 的顶部移除的 Object。 </returns>
public T Pop()
{
T obj = this.index < 0 ? default(T) : this.array[this.index];
if (null != obj)
{
this.index--;
this._count--;
//this.array[this.index] = default(T);
}
return obj;
}

/// <summary>
/// 将对象插入 Stack 的顶部。
/// </summary>
public void Push(T obj)
{
if (null != obj)
{
if (this.index >= this.array.Length - 1)
{
T[] temp = new T[this.array.Length * 2];
int count = 0;
foreach (T item in array)
{
temp[count++] = item;
}
this.array = temp;
}
array[++index] = obj;
this._count++;
}
}
}
}

这是那个栈Demo

C#的动态编译,并返回结果

C# code 
        private void btn_Compute_Click(object sender, EventArgs e)

        {

            // 声明要计算C#代码,要求必须完整的C#代码

            string strCode = @"

                    using System;

                    namespace ParseEx

                    {

                        public class ParseExC

                        {

                            public static double GetValue()  //GetValue(int x) //可以带参数

                            {

                                return 1+5*8-(Math.Sin(12)*2.5);

                            }

                        }

                    }";

            Stopwatch sw = new Stopwatch();

            sw.Start();

            string strCode = @"

                    using System;

                    namespace ParseEx

                    {

                        public class ParseExC

                        {

                            public static double GetValue()

                            {"

            + "return " + this.textBox_Text.Text.Trim() + ";" +

                            @"}

                        }

                    }";

           

            CodeDomProvider comp = new CSharpCodeProvider();

            CompilerParameters cp = new CompilerParameters();

            StringBuilder codeBuilder = new StringBuilder();

            codeBuilder.AppendLine(strCode);

            cp.ReferencedAssemblies.Add("System.dll");

            cp.GenerateExecutable = false;

            cp.GenerateInMemory = true;

            CompilerResults cr = comp.CompileAssemblyFromSource(cp, codeBuilder.ToString());

            if (cr.Errors.HasErrors)

            {

                MessageBox.Show("Error!");

            }

            else

            {

                Assembly a = cr.CompiledAssembly;

                if (a != null)

                {

                    Type t = a.GetType("ParseEx.ParseExC");

                    if (t != null)

                    {

                        // 因为是静态调用,不需要创建实例了

                        // object mode = a.CreateInstance("Mode");

                        MethodInfo mi = t.GetMethod("GetValue", BindingFlags.Static | BindingFlags.Public);

                        if (mi != null)

                        {

                            double d = (double)mi.Invoke(null, null);

//double d = (double)mi.Invoke(null, new object[] { 1 }) });  //可以带参数
                            sw.Stop();

                            this.label_Result.Text = "Result = " + d.ToString() + "; Time = " + sw.Elapsed.ToString();

                            //MessageBox.Show("Result = " + d.ToString());

                        }

                    }

                }

            }

        }

    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息