c#根据公式进行自动计算的实现

 

之前搞了3个不同的方法来实现公式的自动计算,今天又去了老外的codeProject论坛转了一圈,又有了点收获,原来老外也有这方面的需求,这个老外完全是自己用代码实现的,牛,赞一个先。

主要实现的类:

using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  AutoComputer
{
    
class VariFormel
    
{
        
private string vars = "", zc;
        
private double[] values = new double[10];
        
private int pos, klammer, ebene;
        
private double res;
        
private bool fehler = false;

        
/// <summary>
        
/// Rechnet eine Formel aus
        
/// </summary>
        
/// <param name="formel">Der text mit der Formel</param>
        
/// <param name="result">Variable, die das Ergebnis erh鋖t</param>
        
/// <returns>Erfolg der Funktion</returns>

        public bool Neu(string formel, out double result)
        
{
            
if (formel == ""
            
{ result = 0.0return false; }
            fehler 
= false;
            result 
= Zuteilung(formel);
            
return !fehler;
        }


        
/// <summary>
        
/// Rekursive Hauptprozedur, die die Formel ausrechnet
        
/// </summary>
        
/// <param name="Op">Der Text mit der Formel</param>
        
/// <returns>Das Ergebnis der Formel oder 0 bei Fehlern</returns>

        private double Zuteilung(string Op)
        
{
            
if (Op.Length == 0goto fehl;
            
if (Op.StartsWith("("&& GetKlammer(Op, 0== Op.Length - 1
                Op 
= Op.Substring(1, Op.Length - 2);
            
if (double.TryParse(Op, System.Globalization.NumberStyles.Float,nullout res)) 
                
return res;
            
if (Op.Length == 2 && Op == "PI"return Math.PI;
            
if (Op.Length == 1 && TryVariable(Op, out res)) return res;
            
if (Op.Length > 4 && Op.Substring(31== "(")
            
{
                pos 
= GetKlammer(Op, 3);
                
if (pos != Op.Length - 1goto next;
                zc 
= Op.Substring(4, pos - 4);
                
switch (Op.Substring(03))
                
{
                    
case "sqr"return Math.Sqrt(Zuteilung(zc));
                    
case "sin"return Math.Sin(Math.PI * Zuteilung(zc) / 180);
                    
case "cos"return Math.Cos(Math.PI * Zuteilung(zc) / 180);
                    
case "tan"return Math.Tan(Math.PI * Zuteilung(zc) / 180);
                    
case "log"return Math.Log10(Zuteilung(zc));
                    
case "abs"return Math.Abs(Zuteilung(zc));
                    
case "fac"return Faculty(Zuteilung(zc));
                }

            }

        next:
            pos 
= 0; ebene = 6; klammer = 0;
            
for (int i = Op.Length - 1; i > -1; i--)
            
{
                
switch (Op.Substring(i, 1))
                
{
                    
case "(": klammer++break;
                    
case ")": klammer--break;
                    
case "+"if (klammer == 0 && ebene > 0{ pos = i; ebene = 0; } break;
                    
case "-"if (klammer == 0 && ebene > 1{ pos = i; ebene = 1; } break;
                    
case "*"if (klammer == 0 && ebene > 2{ pos = i; ebene = 2; } break;
                    
case "%"if (klammer == 0 && ebene > 3{ pos = i; ebene = 3; } break;
                    
case "/"if (klammer == 0 && ebene > 4{ pos = i; ebene = 4; } break;
                    
case "^"if (klammer == 0 && ebene > 5{ pos = i; ebene = 5; } break;
                }

            }

            
if (pos == 0 || pos == Op.Length - 1goto fehl;
            zc 
= Op.Substring(pos, 1);
            
string t1, t2;
            t1 
= Op.Substring(0, pos);
            t2 
= Op.Substring(pos + 1, Op.Length - (pos + 1));
            
switch (zc)
            
{
                
case "+"return Zuteilung(t1) + Zuteilung(t2);
                
case "-"return Zuteilung(t1) - Zuteilung(t2);
                
case "*"return Zuteilung(t1) * Zuteilung(t2);
                
case "/"return Zuteilung(t1) / Zuteilung(t2);
                
case "%"return Math.IEEERemainder(Zuteilung(t1), Zuteilung(t2));
                
case "^"return Math.Pow(Zuteilung(t1), Zuteilung(t2));
            }

        fehl:
            fehler 
= true;
            
return 0.0;
        }

        
/// <summary>
        
/// Sucht zu einer ge鰂fneten Klammer die Position der entsprechend schlie遝nden Klammer
        
/// </summary>
        
/// <param name="Op">Der zu 黚erpr黤ende Text</param>
        
/// <param name="start">Position der er鰂fnenden Klammer</param>
        
/// <returns>Position der schlie遝nden Klammer, oder START, wenn keine vorhanden</returns>

        private int GetKlammer(string Op, int start)
        
{
            
int res = start;
            
for (int i = start; i < Op.Length; i++)
            
{
                
switch (Op.Substring(i, 1))
                
{
                    
case "(": klammer++break;
                    
case ")": klammer--break;
                }

                
if (klammer == 0{ res = i; break; }
            }

            
return res;
        }

        
/// <summary>
        
/// Pr黤t, ob der Text eine Variable bezeichnet und schreibt den Wert in eine Variable
        
/// </summary>
        
/// <param name="Op">Der zu 黚erpr黤ende Text</param>
        
/// <param name="wert">Adresse der Variable, die den Wert erhalten soll</param>
        
/// <returns>TRUE, wenn eine Variable gefunden wurde</returns>

        private bool TryVariable(string Op, out double wert)
        
{
            
int i = vars.IndexOf(Op);
            
if (i != -1)
            
{
                wert 
= values[i];
                
return true;
            }

            
else
            
{
                wert 
= 0.0;
                
return false;
            }

        }

        
private double Faculty(double number)
        
{
            
if (double.IsInfinity(number) ||
                
double.IsNaN(number) ||
                number 
< 0.0 ||
                number 
% 1.0 != 0return double.NaN;
            
double res = 1.0;
            
for (int i = 0; i < number; i++)
                res 
*= (double)(i + 1);
            
return res;
        }

    }

}


调用部分:
[System.Runtime.InteropServices.DllImport( " user32.dll " )]
        
private   static   extern   int  MessageBeep( int  wType);
        
private   const   int  MB_ICONASTERISK  =   0x40 ;

        
private  VariFormel fml  =   new  VariFormel();

        
private   void  btnCalc_Click( object  sender, EventArgs e)
        
{
            Calculate();
        }

        
private   void  Calculate()
        
{
            
double res;
            
if (!fml.Neu(tbFormel.Text, out res))
            
{
                lblResult.Text 
= "Die Formel enth鋖t Fehler";
                MessageBeep(MB_ICONASTERISK);
            }

            
else
                lblResult.Text 
= res.ToString();
        }

由于比较急,注释部分还没来得及翻译,先讲究着看吧,呵呵
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值