假设一个字符串str="4*36+7+88/12^2",C#如何直接计算出这个字符串变量str的算术值。

时间:2023-01-09 11:26:41
假设一个字符串str="4*36+7+88/12^2",C#如何直接计算出这个字符串变量str的算术值。

12 个解决方案

#1


搜一下“用栈实现表达式求值”。
这是数据结构和算法课程中比较基础的内容,主要思路是用两个堆栈,一个用来存储操作符,一个存储操作数,从字符串中解析出一个元素(数或运算符),通过运算符之间的优先级,控制操作符进栈出栈。出栈是指的弹出两个操作数一个运算符,然后将它们的运算结果再次入栈。直到字符串和两个栈全部为空。

#2


public static object Eval(string AExpression)
{
    try
    {
        return new DataTable().Compute(AExpression, "");
    }
    catch
    {
        return null;
    }
}

#3


楼上有个问题,乘方在C#可不是这么表示阿,四则运算楼上是对的

#4


那是VB的语法。

#5


这个应该可以满足你的基本要求!!   
  #include   <stdio.h>   
  #include   <stdlib.h>   
  #define   init_size   10   
  #define   pp_size   2   
  int   i=0;   
  typedef   struct   
    {char   *base;   
      char   *top;   
      int   size;   
    }optr;   
  typedef   struct   
      {int   *base;   
        int   *top;   
        int   size;   
      }oped;   
  char   lable[8][8]={'   ','+','-','*','/','(',')','#',   
      '+','>','>','<','<','<','>','>',   
      '-','>','>','<','<','<','>','>',   
      '*','>','>','>','>','<','>','>',   
      '/','>','>','>','>','<','>','>',   
      '(','<','<','<','<','<','=','   ',   
      ')','>','>','>','>','   ','>','>',   
      '#','<','<','<','<','<','   ','='   
      };   
    
  void   init_oped(oped   *s)   
            {s->base=(int   *)malloc(init_size*sizeof(int));   
              if(!s->base)   {printf("init   error!");exit(0);}   
              s->top=s->base;   
              s->size=init_size;   
              }   
    
  void   init_optr(optr   *s)   
            {s->base=(char   *)malloc(init_size*sizeof(char));   
              if(!s->base)   {printf("init   error!");exit(0);}   
              s->top=s->base;   
              s->size=init_size;   
              }   
  void   push_oped(oped   *s,int   e)   
            {if(s->top-s->base>=s->size)   
                {s->base=(int   *)realloc(s->base,(init_size+pp_size)*sizeof(int));   
  if(!s->base)   {printf("puss_oped   error!");exit(0);}   
  s->top=s->base+s->size;   
  s->size+=pp_size;   
  }   
  *s->top=e;   
  s->top++;   
            }   
  void   push_optr(optr   *s,char   e)   
            {if(s->top-s->base>=s->size)   
                {s->base=(char   *)realloc(s->base,(init_size+pp_size)*sizeof(char));   
  if(!s->base)   {printf("push_optr   error!");exit(0);}   
  s->top=s->base+s->size;   
  s->size+=pp_size;   
  }   
  *s->top=e;   
  s->top++;   
            }   
  char   pop_optr(optr   *s)   
            {char   ch;   
              if(s->top==s->base)   {printf("optr-stack   NULL!");exit(0);}   
              ch=*(--s->top);   
              return   ch;   
            }   
    
  int   pop_oped(oped   *s)   
            {int   ch;   
              if(s->top==s->base)   {printf("oped-stack   NULL!");exit(0);}   
              ch=*(--s->top);   
              return   ch;   
            }   
  char   gettop(optr   *s)   
            {char   ch;   
              if(s->top==s->base)   {printf("gettop   stack   NULL   error!");exit(0);}   
              ch=*(s->top-1);   
              return   ch;   
            }   
  char   precede(char   x,char   y)   
            {char   ch;   
              int   i,j;   
              for(i=0;i<8;i++)   
                if(lable[i][0]==x)   break;   
              for(j=0;j<8;j++)   
                if(lable[0][j]==y)   break;   
              ch=lable[i][j];   
              return   ch;   
            }   
  int   operate(int   x,char   ch,int   y)   
          {int   sum=0;   
            switch   (ch)   
            {case   '+':sum=x+y;break;   
              case   '-':sum=x-y;break;   
              case   '*':sum=x*y;break;   
              case   '/':sum=x/y;break;   
              }   
            return   sum;   
          }   
  main()   
  {optr   *p;   
    oped   *s;   
    char   ch,op;   
    int   sum=0,temp,a,b;   
    init_optr(p);push_optr(p,'#');   
    init_oped(s);   
    printf("\nplease   enter   :");   
    ch=getchar();   
    while(ch!='#'||(op=gettop(p))!='#')   
      {if(ch>='0'&&ch<='9')   
            {sum=sum*10+(ch-'0');ch=getchar();}   
        else   {push_oped(s,sum);   
    sum=0;   
    
        A1:       switch   (precede(gettop(p),ch))   
    {case   '<':push_optr(p,ch);ch=getchar();break;   
      case   '=':if(ch=='#')   break;   
        else   {pop_optr(p);   
    ch=getchar();   
    break;}   
      case   '>':{b=pop_oped(s);op=pop_optr(p);a=pop_oped(s);   
          temp=operate(a,op,b);   
          push_oped(s,temp);   
          goto   A1;   
          }   
    }   
    }   
        }   
      printf("\ncomeout:%d",pop_oped(s));   
    }

#6


// SuperCalc.cs - 超级计算器

using System;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;
using System.Reflection;
using System.Text;
using System.Globalization;

namespace Skyiv
{
  class SuperCalc : Form
  {
    TextBox tbxA1;
    TextBox tbxA3;

    [STAThread]
    static void Main(string [] args)
    {
      Application.Run(new SuperCalc());
    }

    SuperCalc()
    {
      Text              = "Super Calculator";
      StartPosition     = FormStartPosition.CenterScreen;
      Width             = 300;
      Height            = 300;

      tbxA1             = new TextBox();
      tbxA1.Parent      = this;
      tbxA1.Multiline   = true;
      tbxA1.WordWrap    = false;
      tbxA1.Dock        = DockStyle.Fill;
      tbxA1.BorderStyle = BorderStyle.FixedSingle;

      Panel pnlA1       = new Panel();
      pnlA1.Parent      = this;
      pnlA1.Height      = 22;
      pnlA1.Dock        = DockStyle.Top;

      tbxA3             = new TextBox();
      tbxA3.Parent      = pnlA1;
      tbxA3.Dock        = DockStyle.Fill;
      tbxA3.BorderStyle = BorderStyle.FixedSingle;
      tbxA3.ReadOnly    = true;

      Button btnA3      = new Button();
      btnA3.Text        = "&Calculate";
      btnA3.Parent      = pnlA1;
      btnA3.Width       = 80;
      btnA3.Dock        = DockStyle.Left;
      btnA3.Click      += new EventHandler(Calc_Clicked);
    }

    void Calc_Clicked(object sender, EventArgs ea)
    {
      (sender as Control).Enabled = false;
      try
      {
        tbxA3.Text = (new Expression(tbxA1.Text)).Compute().ToString();
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error");
      }
      finally
      {
        (sender as Control).Enabled = true;
      }
    }
  }


  // VBExpression.cs - 动态生成数学表达式并计算其值
  // 表达式使用 Visual Baisc 语法
  // 可使用 pi、e 等常量,sin、cos、tan、log、sqrt 等函数

  sealed class Expression
  {
    object instance;
    MethodInfo method;

    public Expression(string expression)
    {
      if (expression.ToUpper(CultureInfo.InvariantCulture).IndexOf("RETURN") < 0)
      {
        expression = "Return " + expression.Replace(Environment.NewLine, " ");
      }
      string className = "Expression";
      string methodName = "Compute";
      CompilerParameters p = new CompilerParameters();
      p.GenerateInMemory = true;
      CompilerResults cr = new VBCodeProvider().CompileAssemblyFromSource
      (
        p,
        string.Format
        (
          @"Option Explicit Off
          Option Strict Off
          Imports System, System.Math, Microsoft.VisualBasic
          NotInheritable Class {0}
          Public Function {1} As Double
          {2}
          End Function
          End Class",
          className, methodName, expression
        )
      );
      if(cr.Errors.Count > 0)
      {
        string msg = "Expression(\"" + expression + "\"): \n";
        foreach (CompilerError err in cr.Errors) msg += err.ToString() + "\n";
        throw new Exception(msg);
      }
      instance = cr.CompiledAssembly.CreateInstance(className);
      method = instance.GetType().GetMethod(methodName);
    }

    public double Compute()
    {
      return (double)method.Invoke(instance, null);
    }
  }
}

#7


假设一个字符串str="4*36+7+88/12^2",C#如何直接计算出这个字符串变量str的算术值。

#9


很好很强大~~

#10


难道net框架里就没有解决这个问题的类?

#11


mark
慢慢看

#12


引用 6 楼 *8808 的回复:
C# code
// SuperCalc.cs - 超级计算器

using System;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;
using System.Reflection;
using System.Text;
using System.Global……


果然是无敌方法!!!——在效率方面:

DataTable 的 Compute()  在计算时:速度特别快!——基本的加减法几乎不消耗时间

楼主的:
Expression 的 Compute()  在计算时:速度都保持在 300 毫秒 左右!——基本的加减法也消耗这么多的时间:估计是在 编译时浪费了时间;

——但是,不容否认:Expression  真的很无敌.....

#1


搜一下“用栈实现表达式求值”。
这是数据结构和算法课程中比较基础的内容,主要思路是用两个堆栈,一个用来存储操作符,一个存储操作数,从字符串中解析出一个元素(数或运算符),通过运算符之间的优先级,控制操作符进栈出栈。出栈是指的弹出两个操作数一个运算符,然后将它们的运算结果再次入栈。直到字符串和两个栈全部为空。

#2


public static object Eval(string AExpression)
{
    try
    {
        return new DataTable().Compute(AExpression, "");
    }
    catch
    {
        return null;
    }
}

#3


楼上有个问题,乘方在C#可不是这么表示阿,四则运算楼上是对的

#4


那是VB的语法。

#5


这个应该可以满足你的基本要求!!   
  #include   <stdio.h>   
  #include   <stdlib.h>   
  #define   init_size   10   
  #define   pp_size   2   
  int   i=0;   
  typedef   struct   
    {char   *base;   
      char   *top;   
      int   size;   
    }optr;   
  typedef   struct   
      {int   *base;   
        int   *top;   
        int   size;   
      }oped;   
  char   lable[8][8]={'   ','+','-','*','/','(',')','#',   
      '+','>','>','<','<','<','>','>',   
      '-','>','>','<','<','<','>','>',   
      '*','>','>','>','>','<','>','>',   
      '/','>','>','>','>','<','>','>',   
      '(','<','<','<','<','<','=','   ',   
      ')','>','>','>','>','   ','>','>',   
      '#','<','<','<','<','<','   ','='   
      };   
    
  void   init_oped(oped   *s)   
            {s->base=(int   *)malloc(init_size*sizeof(int));   
              if(!s->base)   {printf("init   error!");exit(0);}   
              s->top=s->base;   
              s->size=init_size;   
              }   
    
  void   init_optr(optr   *s)   
            {s->base=(char   *)malloc(init_size*sizeof(char));   
              if(!s->base)   {printf("init   error!");exit(0);}   
              s->top=s->base;   
              s->size=init_size;   
              }   
  void   push_oped(oped   *s,int   e)   
            {if(s->top-s->base>=s->size)   
                {s->base=(int   *)realloc(s->base,(init_size+pp_size)*sizeof(int));   
  if(!s->base)   {printf("puss_oped   error!");exit(0);}   
  s->top=s->base+s->size;   
  s->size+=pp_size;   
  }   
  *s->top=e;   
  s->top++;   
            }   
  void   push_optr(optr   *s,char   e)   
            {if(s->top-s->base>=s->size)   
                {s->base=(char   *)realloc(s->base,(init_size+pp_size)*sizeof(char));   
  if(!s->base)   {printf("push_optr   error!");exit(0);}   
  s->top=s->base+s->size;   
  s->size+=pp_size;   
  }   
  *s->top=e;   
  s->top++;   
            }   
  char   pop_optr(optr   *s)   
            {char   ch;   
              if(s->top==s->base)   {printf("optr-stack   NULL!");exit(0);}   
              ch=*(--s->top);   
              return   ch;   
            }   
    
  int   pop_oped(oped   *s)   
            {int   ch;   
              if(s->top==s->base)   {printf("oped-stack   NULL!");exit(0);}   
              ch=*(--s->top);   
              return   ch;   
            }   
  char   gettop(optr   *s)   
            {char   ch;   
              if(s->top==s->base)   {printf("gettop   stack   NULL   error!");exit(0);}   
              ch=*(s->top-1);   
              return   ch;   
            }   
  char   precede(char   x,char   y)   
            {char   ch;   
              int   i,j;   
              for(i=0;i<8;i++)   
                if(lable[i][0]==x)   break;   
              for(j=0;j<8;j++)   
                if(lable[0][j]==y)   break;   
              ch=lable[i][j];   
              return   ch;   
            }   
  int   operate(int   x,char   ch,int   y)   
          {int   sum=0;   
            switch   (ch)   
            {case   '+':sum=x+y;break;   
              case   '-':sum=x-y;break;   
              case   '*':sum=x*y;break;   
              case   '/':sum=x/y;break;   
              }   
            return   sum;   
          }   
  main()   
  {optr   *p;   
    oped   *s;   
    char   ch,op;   
    int   sum=0,temp,a,b;   
    init_optr(p);push_optr(p,'#');   
    init_oped(s);   
    printf("\nplease   enter   :");   
    ch=getchar();   
    while(ch!='#'||(op=gettop(p))!='#')   
      {if(ch>='0'&&ch<='9')   
            {sum=sum*10+(ch-'0');ch=getchar();}   
        else   {push_oped(s,sum);   
    sum=0;   
    
        A1:       switch   (precede(gettop(p),ch))   
    {case   '<':push_optr(p,ch);ch=getchar();break;   
      case   '=':if(ch=='#')   break;   
        else   {pop_optr(p);   
    ch=getchar();   
    break;}   
      case   '>':{b=pop_oped(s);op=pop_optr(p);a=pop_oped(s);   
          temp=operate(a,op,b);   
          push_oped(s,temp);   
          goto   A1;   
          }   
    }   
    }   
        }   
      printf("\ncomeout:%d",pop_oped(s));   
    }

#6


// SuperCalc.cs - 超级计算器

using System;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;
using System.Reflection;
using System.Text;
using System.Globalization;

namespace Skyiv
{
  class SuperCalc : Form
  {
    TextBox tbxA1;
    TextBox tbxA3;

    [STAThread]
    static void Main(string [] args)
    {
      Application.Run(new SuperCalc());
    }

    SuperCalc()
    {
      Text              = "Super Calculator";
      StartPosition     = FormStartPosition.CenterScreen;
      Width             = 300;
      Height            = 300;

      tbxA1             = new TextBox();
      tbxA1.Parent      = this;
      tbxA1.Multiline   = true;
      tbxA1.WordWrap    = false;
      tbxA1.Dock        = DockStyle.Fill;
      tbxA1.BorderStyle = BorderStyle.FixedSingle;

      Panel pnlA1       = new Panel();
      pnlA1.Parent      = this;
      pnlA1.Height      = 22;
      pnlA1.Dock        = DockStyle.Top;

      tbxA3             = new TextBox();
      tbxA3.Parent      = pnlA1;
      tbxA3.Dock        = DockStyle.Fill;
      tbxA3.BorderStyle = BorderStyle.FixedSingle;
      tbxA3.ReadOnly    = true;

      Button btnA3      = new Button();
      btnA3.Text        = "&Calculate";
      btnA3.Parent      = pnlA1;
      btnA3.Width       = 80;
      btnA3.Dock        = DockStyle.Left;
      btnA3.Click      += new EventHandler(Calc_Clicked);
    }

    void Calc_Clicked(object sender, EventArgs ea)
    {
      (sender as Control).Enabled = false;
      try
      {
        tbxA3.Text = (new Expression(tbxA1.Text)).Compute().ToString();
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error");
      }
      finally
      {
        (sender as Control).Enabled = true;
      }
    }
  }


  // VBExpression.cs - 动态生成数学表达式并计算其值
  // 表达式使用 Visual Baisc 语法
  // 可使用 pi、e 等常量,sin、cos、tan、log、sqrt 等函数

  sealed class Expression
  {
    object instance;
    MethodInfo method;

    public Expression(string expression)
    {
      if (expression.ToUpper(CultureInfo.InvariantCulture).IndexOf("RETURN") < 0)
      {
        expression = "Return " + expression.Replace(Environment.NewLine, " ");
      }
      string className = "Expression";
      string methodName = "Compute";
      CompilerParameters p = new CompilerParameters();
      p.GenerateInMemory = true;
      CompilerResults cr = new VBCodeProvider().CompileAssemblyFromSource
      (
        p,
        string.Format
        (
          @"Option Explicit Off
          Option Strict Off
          Imports System, System.Math, Microsoft.VisualBasic
          NotInheritable Class {0}
          Public Function {1} As Double
          {2}
          End Function
          End Class",
          className, methodName, expression
        )
      );
      if(cr.Errors.Count > 0)
      {
        string msg = "Expression(\"" + expression + "\"): \n";
        foreach (CompilerError err in cr.Errors) msg += err.ToString() + "\n";
        throw new Exception(msg);
      }
      instance = cr.CompiledAssembly.CreateInstance(className);
      method = instance.GetType().GetMethod(methodName);
    }

    public double Compute()
    {
      return (double)method.Invoke(instance, null);
    }
  }
}

#7


假设一个字符串str="4*36+7+88/12^2",C#如何直接计算出这个字符串变量str的算术值。

#8


#9


很好很强大~~

#10


难道net框架里就没有解决这个问题的类?

#11


mark
慢慢看

#12


引用 6 楼 *8808 的回复:
C# code
// SuperCalc.cs - 超级计算器

using System;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;
using System.Reflection;
using System.Text;
using System.Global……


果然是无敌方法!!!——在效率方面:

DataTable 的 Compute()  在计算时:速度特别快!——基本的加减法几乎不消耗时间

楼主的:
Expression 的 Compute()  在计算时:速度都保持在 300 毫秒 左右!——基本的加减法也消耗这么多的时间:估计是在 编译时浪费了时间;

——但是,不容否认:Expression  真的很无敌.....