zoukankan      html  css  js  c++  java
  • 【类】C#计算器类(SamWang)

      1 /******************************************************************
      2  * 创 建 人:  SamWang
      3  * 创建时间:  2011-11-29
      4  * 描    述:
      5  *             计算器类:能直接对表达式进行计算,支持变量
      6  * 原    理:  将表达式按字符压入堆栈中,然后按照各操作符的级别进行处理
      7  * 版    本:  V1.0      
      8  * 环    境:  VS2005
      9 ******************************************************************/
     10 using System;
     11 using System.Collections.Generic;
     12 using System.Text;
     13 using System.Windows.Forms;
     14 using System.Collections;
     15 
     16 namespace LingDang.CRM.UI.Client
     17 {
     18     public class Calculator
     19     {
     20         private string _expression;
     21         private Stack s;
     22         private string[] values;
     23 
     24         /// <summary>
     25         /// 构造函数
     26         /// </summary>
     27         /// <param name="expression">表达式</param>
     28         /// <param name="varValues">变量值数组</param>
     29         public Calculator(string expression, string[] varValues)
     30         {
     31             this._expression = expression.ToLower();
     32             s = new Stack();
     33             values = varValues;
     34         }
     35 
     36         /// <summary>
     37         /// 构造函数
     38         /// </summary>
     39         /// <param name="expression">表达式</param>
     40         public Calculator(string expression)
     41         {
     42             this._expression = expression;
     43             s = new Stack();
     44         }
     45 
     46         /// <summary>
     47         /// 总运行
     48         /// </summary>
     49         /// <returns></returns>
     50         public double Run()
     51         {
     52             string expression = PostFix();
     53             string[] aryString = expression.Split('|');
     54 
     55             foreach (string str in aryString)
     56             {
     57                 if (IsNumber(str) || IsVarible(str[0]))
     58                 {
     59                     double d;
     60                     if (IsVarible(str[0]))
     61                     {
     62                         d = Convert.ToDouble(GetValue(str[0]));
     63                     }
     64                     else
     65                     {
     66                         d = Convert.ToDouble(str.ToString());
     67                     }
     68                     AddOperands(d);
     69                 }
     70                 else
     71                 {
     72                     DoOperator(str);
     73                 }
     74 
     75             }
     76             return (double)s.Pop();
     77         }
     78 
     79 
     80         private bool IsNumber(string str)
     81         {
     82             if (str.Length > 1)
     83             {
     84                 return true;
     85             }
     86             else
     87             {
     88                 return Char.IsDigit(str[0]);
     89             }
     90         }
     91 
     92         /// <summary>
     93         /// 判断是否为变量,变量范围为a-z
     94         /// </summary>
     95         /// <param name="c"></param>
     96         /// <returns></returns>
     97         private bool IsVarible(char c)
     98         {
     99             if (c >= 'a' && c <= 'z')
    100             {
    101                 return true;
    102             }
    103             else
    104             {
    105                 return false;
    106             }
    107         }
    108 
    109 
    110         private void AddOperands(double val)
    111         {
    112             s.Push(val);
    113         }
    114 
    115         /// <summary>
    116         /// 得到公式左右运算数
    117         /// </summary>
    118         /// <param name="left"></param>
    119         /// <param name="right"></param>
    120         /// <returns></returns>
    121         private bool GetTwoOperands(out double left, out double right)
    122         {
    123             try
    124             {
    125                 right = (double)s.Pop();
    126                 left = (double)s.Pop();
    127             }
    128             catch (InvalidOperationException)
    129             {
    130                 right = 0;
    131                 left = 0;
    132                 return false;
    133             }
    134             return true;
    135         }
    136 
    137         /// <summary>
    138         /// 计算操作
    139         /// </summary>
    140         /// <param name="op">运算符</param>
    141         private void DoOperator(string op)
    142         {
    143             double left, right;
    144             bool result = GetTwoOperands(out left, out right);
    145             if (result)
    146             {
    147                 switch (op)
    148                 {
    149                     case "+": s.Push(left + right); break;
    150                     case "-": s.Push(left - right); break;
    151                     case "*": s.Push(left * right); break;
    152                     case "/":
    153                         if (right == 0.0)
    154                         {
    155                             s.Clear();
    156                             //Divide by 0!
    157                             throw new Exception("除数不能为零");
    158                         }
    159                         else
    160                             s.Push(left / right);
    161                         break;
    162                     case "^":
    163                         s.Push(Math.Pow(left, right));
    164                         break;
    165                 }
    166             }
    167             else
    168             {
    169                 s.Clear();
    170             }
    171         }
    172 
    173         /// <summary>
    174         /// 解析为后缀表达式
    175         /// </summary>
    176         /// <returns></returns>
    177         public string PostFix()
    178         {
    179             string str = this._expression + "#";
    180             char tempc;
    181             char[] chars = str.ToCharArray();
    182             Stack ts = new Stack();
    183             ts.Push('#');
    184             string str1 = "";
    185             string tmpStr = "";
    186             bool isNum = false;
    187             foreach (char c in chars)
    188             {
    189                 if (Char.IsDigit(c) || IsVarible(c) || c == '.')
    190                 {
    191                     tmpStr += c.ToString();
    192                     isNum = true;
    193                 }
    194                 else
    195                 {
    196                     if (isNum)
    197                     {
    198                         str1 += tmpStr + "|";
    199                         tmpStr = "";
    200                     }
    201                     isNum = false;
    202                     if (c == ')')
    203                     {
    204                         for (tempc = Convert.ToChar(ts.Pop()); tempc != '('; tempc = Convert.ToChar(ts.Pop()))
    205                             str1 += tempc.ToString() + "|";
    206                     }
    207                     else
    208                     {
    209                         for (tempc = Convert.ToChar(ts.Pop()); Isp(tempc) > Icp(c); tempc = Convert.ToChar(ts.Pop()))
    210                             str1 += tempc.ToString() + "|";
    211                         ts.Push(tempc);
    212                         ts.Push(c);
    213                     }
    214                 }
    215             }
    216             return str1.Substring(0, str1.Length - 1);
    217         }
    218 
    219         /// <summary>
    220         /// 根据变量名得到对应的值
    221         /// </summary>
    222         /// <param name="c">变量名:A-Z</param>
    223         /// <returns></returns>
    224         private string GetValue(char c)
    225         {
    226             string result = "0";
    227             //变量对应的数组位置
    228             int index = Convert.ToInt32(c) - Convert.ToInt32('a');
    229             if (index < values.Length)
    230             {
    231                 result = values[index].ToString();
    232             }
    233             return result;
    234         }
    235 
    236         private int Isp(char c)
    237         {
    238             int k;
    239             switch (c)
    240             {
    241                 case '#': k = 0; break;
    242                 case '(': k = 1; break;
    243                 case '^': k = 7; break;
    244                 case '*':
    245                 case '/':
    246                 case '%': k = 5; break;
    247                 case '+':
    248                 case '-': k = 3; break;
    249                 case ')': k = 8; break;
    250                 default:
    251                     //Unknown operator!
    252                     throw new Exception("无效操作符:"+c.ToString());
    253             }
    254             return k;
    255         }
    256 
    257         private int Icp(char c)
    258         {
    259             int k;
    260             switch (c)
    261             {
    262                 case '#': k = 0; break;
    263                 case '(': k = 8; break;
    264                 case '^': k = 6; break;
    265                 case '*':
    266                 case '/':
    267                 case '%': k = 4; break;
    268                 case '+':
    269                 case '-': k = 2; break;
    270                 case ')': k = 1; break;
    271                 default:
    272                     //Unknown operator!
    273                     throw new Exception("无效操作符:" + c.ToString());
    274             }
    275             return k;
    276         }
    277     }
    278 }

    作者:SamWang
    出处:http://wangshenhe.cnblogs.com/
    本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。

  • 相关阅读:
    C#实现函数超出指定时间,自动退出
    批量下载github代码,同时含有解压zip,遍历文件函数
    MSBuild构建工作空间,解决project.Documents.Count()=0的问题
    使用Roslyn 使用MSBuild进行编译,项目不报错,但是运行显示ReflectionTypeLoadException,解决方案
    基于roslyn实现函数与函数之间的依赖关系
    discount C#
    对Symbol的获取(Roslyn)
    AcWing 955. 维护数列(splay插入,删除,区间修改,区间翻转,区间求和,区间求最大子段和)
    AcWing 1063. 永无乡(并查集, 启发式合并,splay)
    AcWing 2437. Splay
  • 原文地址:https://www.cnblogs.com/wangshenhe/p/2492093.html
Copyright © 2011-2022 走看看