正文

c#实现字符串算数表达式计算2008-07-26 15:42:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/iamben250/37114.html

分享到:

Function Evaluator
Rating:

Emad Barsoum (view profile)
December 4, 2002


(continued)



Turbo Screen Sharing
Adobe Acrobat Connect Professional offers users the ability to have a more productive and engaging web conferencing experience while providing the IT department with a program that efficiently utilizes bandwidth and minimally impacts the infrastructure. Learn More! »

Informal Learning: Extending the Impact of Enterprise Ideas and Information
Forward-thinking organizations are turning to enterprise learning in their quest to be better informed, better skilled, better supported at the point of need, and more competitive in their respective marketplaces. Learn More! »

Rapid E-Learning: Maturing Technology Brings Balance and Possibilities
Rapid e-learning addresses both time and cost issues by using technology tools to shift the dynamics of e-learning development. Learn why more skilled learning professionals use these tools and how you can get a solution to keep pace with your business demands. »

Delivering on the Promise of ELearning
This white paper defines the framework to launch e-learning as a set of teaching, training, and learning practices not bound by a specific technology platform or learning management system. It offers practical suggestions for creating digital learning experiences that engage learners by building interest and motivation and providing opportunities for active participation. »

Environment: Visual C# Ver 1.0, .NET Platform Ver 1.0, Windows XP, Windows 2000 SP2

Abstract

This program uses the transformation from infix notation to postfix notation to evaluate most mathematic expressions. It supports most operators (+, -, *, /, %, and ^), functions from 0 to any number of parameters, and also a user-defined function by using a delegate. Also, it supports variables in the expression; it will generate a symbol table that can be updated at run time. Also, this program demonstrates the use of a DataGrid as a normal grid without any database connection.

Details

All the code neccessary to transform an infix expression to a postfix expression and evaluate the postfix expression is encapsulated in the "Function" class. Also, this class supports a variable; this means you can write expressions such as "num1 + num2". It automatically generates the symbol table for it, and initializes all variables to zero by default.

The first member function that must be called in the Function class is "Parse", which takes the expression string as a parameter and transforms it to an an "ArrayList" of Symbol, and stores it in the member variable "m_equation". The Symbol is a structure that contains information about any symbol, which is the smallest element in any equation. It contains the following information:

  • m_name: the name of the symbol which may be "num1", "+", "cos" ,"(", "7", and so forth.
  • m_type: the type of this symbol that is defined in the enumerator Type, which may be variable, value, operator, comma, and so on.
  • m_value: the value of that symbol valid only if it is a variable or value.

After that, you must call the member function "Infix2Postfix", which transforms the infix notation stored in m_equation to postfix notation and stores it in the m_postfix member variable. If the expression contain any variables, you can call the Variables property to get the symbol table as an ArrayList of Symbol structures. This array contains all variable type symbols only. After changing the value of any variable, just call the "Variables" property again and put on it the updated symbol table. This property is both get and set.

After that, you can call the member function "EvaluatePostfix" to evaluate the expression. The result will be stored as a double in the m_result member variable, which can be accessed by the property member "Result".

Also, this Class has a number of defined functions that can be used directly in any expression. These functions are case sensitive and must be all small. The following are the built-in functions:

Function Description
cos() Takes a single parameter of a radius angle and returns the "cos" of it.
sin() Takes a single parameter of a radius angle and returns the "sin" of it.
tan() Takes a single parameter of a radius angle and returns the "tan" of it.
cosh() Takes a single parameter of a radius angle and returns the "cosh" of it.
sinh() Takes a single parameter of a radius angle and returns the "sinh" of it.
tanh() Takes a single parameter of a radius angle and returns the "tanh" of it.
ln() Takes a single parameter of a number and returns the "ln" of it, which is the logarithm of base "e".
log() Takes a single parameter of a number and returns the "log" of it, which is the logarithm of base "10".
logn() Takes two parameters; the first is a number that we want to compute the logarithm of; the second parameter is the base of the logarithm.
sqrt() Takes a single parameter number and returns its square root.
abs() Takes a single parameter number and returns its absolute value.
acos() Takes a single parameter number and returns its "arc cos".
asin() Takes a single parameter number and returns its "arc sin".
atan() Takes a single parameter number and returns its "arc tan".
exp() Takes a single parameter number and returns its exponent.

Also, you can define your own functions; those functions can contain from zero to any number of parameters. To define your own functions, you must define a delegate function of the following type: "EvaluateFunctionDelegate". This type is defined in Function.cs; then call the "DefaultFunctionEvaluation" property member to set your delegate function. All the functions that you have defined in the delegate function will be added to the built-in function.

Also, the variable "pi" is internally recognized as 3.14159265358979, and the variable "e" is internally recognized as 2.71828182845905. If any error happens, whatever the error type, the error property will return true and the description of the error will be returned by the ErrorDescription property member.

Here some examples of how to use the Function class:

    //-- Example 1: Simple --
    Function fn = new Function();
    fn.Parse("1+2");
    fn.Infix2Postfix();
    fn.EvaluatePostfix();
    double nResult = fn.Result;

//------------------------------------------------------------

    //-- Example 2: How to use built-in function --
    Function fn = new Function();
    fn.Parse("1+2*5-cos(pi)");
    fn.Infix2Postfix();
    fn.EvaluatePostfix();
    double nResult = fn.Result;

//----------------------------------------------------------------

    //-- Example 3: How to use the variable --
    Function fn = new Function();
    fn.Parse("x+2*y-cos(pi)");
    fn.Infix2Postfix();
    ArrayList var = fn.Variables;
    foreach(Symbol sym in var)
    {
      if(sym..m_name == "x")
         sym.m_value = 1;
      else if(sym..m_name == "y")
              sym.m_value = 5;
             }
    fn.Variables = var;
    fn.EvaluatePostfix();
    double nResult = fn.Result;

//----------------------------------------------------------------

    //-- Example 4: How to use the recursive function call --
    Function fn = new Function();
    fn.Parse("sin(cos(pi)*pi/2)");
    fn.Infix2Postfix();
    fn.EvaluatePostfix();
    double nResult = fn.Result;

//----------------------------------------------------------------

    //-- Example 5: How to extend the built-in existing function
    //   using a delegate --

    //-- Let's say you want to add a function called Add that takes
    //   two numbers and returns the sum of both numbers
    //-- The function will be implemented like that --

    public Symbol EvaluateFnc(string name,params Object[] args)
    {
      Symbol result;
      result.m_name = "";
      result.m_type = EB.Math.Type.Result;
      result.m_value = 0;
      switch(name)
      {
           case "add":
           if(args.Length == 2)
           {
             result.m_name = name + "(" +
             ((Symbol)args[0]).m_value.ToString() + ")";
                      result.m_value = ((Symbol)args[0]).m_value +
             ((Symbol)args[1]).m_value;
           }
           else
           {
             result.m_name = "Invalid number of parameters in:
                             "+ name +".";
             result.m_type = EB.Math.Type.Error;
           }
           break;
           default:
           {
             result.m_name = "Function: "+ name +",
                              not found.";
             result.m_type = EB.Math.Type.Error;
           }
           break;
         }
         return result;
       }

    //-- After that, to register this function in the Function
    //   class, do the following:

    Function fn = new Function();
    fn.DefaultFunctionEvaluation = new
EvaluateFunctionDelegate(EvaluateFnc);


//----------------------------------------------------------------

The other part of the program demonstrates how to use the Function class; it also demonstrates how to use DataGrid as a normal grid to show the symbol table without any database connection. To use this program, after compiling the program, write any mathematic expression in the edit box; then click parse. If the expression contains any variable, you can change the value of this variable in the DataGrid Control. After that, click Evaluate to see the result.

N.B.: This class does not handle errors in the expression. This means any error can get through an exception and terminate the program.

Downloads

Download demo project - 13 Kb
Download source - 3 Kb

阅读(4956) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册