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

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

               

 /*
 * 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.Appen

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/ffghggf/article/details/87913214