/// <summary> /// Method of the Scanfkt: reads a constant_identifier. /// </summary> public void ScanFkt_ConstantIdentifier() { string buf = string.Empty; string buf1 = string.Empty; ushort i; do { buf = buf + this.ch; buf1 = buf1 + this.ch_; this.ScanFkt_GetCh(); }while (((this.ch >= 'A') && (this.ch <= 'Z')) || (Constants.spezialChars.IndexOf(this.ch) >= 0)); i = 0; while (i < Constants.konstante.Length) { if ((Constants.konstante[i].bez.ToLower().CompareTo(buf.ToLower()) == 0) && (!this.noUpCase || (Constants.konstante[i].bez.CompareTo(buf1) == 0))) { this.sym = symTyp.istKonst; this.kVar = this.ScanFkt_MakeNode(null, symTyp.istKonst, null); this.kVar.Name = Constants.konstante[i].bez; this.kVar.Nr = i; this.kVar.Zwert = Constants.konstante[i].wert; return; } i++; } // keine Konstantenbezeichnung gefunden ScanFkt_Err(7); }
/// <summary> /// ScanFkt - scans the function string and builds a function tree when successful. /// </summary> /// <param name="fx0"> /// function tree /// </param> /// <param name="funcStr0"> /// function string to scan /// </param> public void ScanFkt(ref FunctionCalcTree fx0, string funcStr0) { if (funcStr0 != string.Empty) { this.maxLang = (byte)funcStr0.Length; this.funcStr = funcStr0; this.fx = fx0; this.fFormel = string.Empty; this.chPos = -1; this.oldChPos = -1; this.ch = ' '; this.fehler = false; this.errPos = 0; this.errNr = 0; this.ScanFkt_GetSym(); this.ScanFkt_Expression(ref this.fx); } else { this.errNr = 6; } this.lastErrNr = (byte)this.errNr; this.lastErrPos = this.errPos; if (this.errNr == 0) { fx0 = this.fx; } }
/// <summary> /// The fkt wert. /// </summary> /// <param name="fx"> /// function. /// </param> /// <param name="nr"> /// number of variable - in this version unused /// </param> /// <returns> /// value <see cref="double"/> . /// </returns> public double FktWert(FunctionCalcTree fx, int nr) { double result; if (fx != null) { this.calcErr = false; this.fktWertError = false; result = this.FktWert_Berechne(fx, nr); if (this.fktWertError) { if (this.calcErr) { result = Constants.fehlerZahl; } else { result = Constants.leerFeld; } } } else { result = Constants.fehlerZahl; this.calcErr = true; } return(result); }
/// <summary> /// Method of the Scanfkt: reads an identifier. /// </summary> public void ScanFkt_Identifier() { string buf = string.Empty; string buf1 = string.Empty; do { buf = buf + this.ch; buf1 = buf1 + this.ch_; this.ScanFkt_GetCh(); }while ((this.ch >= 'A') && (this.ch <= 'Z')); if (buf == "PI") { this.sym = symTyp.istZahl; this.wert = Math.PI; return; } if (buf == "E") { if (this.ch == '^') { this.sym = symTyp.expf; this.ScanFkt_GetCh(); return; } else { this.sym = symTyp.istZahl; this.wert = Constants.eulerZahl; return; } } // teste auf Funktionsbezeichner this.sym = symTyp.sinf; while ((this.sym < symTyp.ffmax) && (buf != Constants.fnam[(int)this.sym - 5])) { this.sym++; } if (this.sym == symTyp.ffmax) { if (buf.ToLower().CompareTo(Constants.varName.ToLower()) == 0) { this.sym = symTyp.ident; if (this.xVar == null) { this.xVar = this.ScanFkt_MakeNode(null, symTyp.ident, null); this.xVar.Zwert = 0; this.xVar.Name = buf1; } } else { ScanFkt_Err(7); } } }
/// <summary> /// Calculates the value of a function for a given number. /// </summary> /// <param name="fx"> /// function /// </param> /// <param name="x"> /// given number /// </param> /// <returns> /// calculateted value <see cref="double"/> . /// </returns> public double FreierFktWert(FunctionCalcTree fx, double x) { double result; this.varXwert = x; result = this.FktWert(fx, -1); return(result); }
/// <summary> /// Makes a node in the function tree. /// </summary> /// <param name="op1"> /// op1 - left tree/operand /// </param> /// <param name="code"> /// code - operator /// </param> /// <param name="op2"> /// op2 right tree/operand /// </param> /// <returns> /// The <see cref="CalculatorFunctionTerm"/> . /// </returns> public FunctionCalcTree ScanFkt_MakeNode(FunctionCalcTree op1, symTyp code, FunctionCalcTree op2) { FunctionCalcTree result; result = new FunctionCalcTree(); result.Cwert = code; result.Li = op1; result.Re = op2; return(result); }
/// <summary> /// clears the function tree /// </summary> /// <param name="fx"> /// function tree /// </param> public void Loesch(ref FunctionCalcTree fx) { if (fx != null) { this.Loesch(ref fx.Li); this.Loesch(ref fx.Re); // fx.free fx = null; } }
/// <summary> /// The textbox1 text changed_1. /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void TextBox1TextChanged1(object sender, TextChangedEventArgs e) { var formelStr = this.textBox1.Text; if (usesDecimalkomma) { formelStr = formelStr.Replace('.', ','); } else { formelStr = formelStr.Replace(',', '.'); } string hilfStr = string.Empty; var aktParser = new Parse(); this.scannedFkt = null; aktParser.ScanFkt(ref this.scannedFkt, formelStr); if (aktParser.lastErrNr > 0) { if (this.art == TRechnerArt.formelRechner) { this.buttonFertig.IsEnabled = false; } else { this.textBoxErgebnis.Text = string.Empty; } aktParser.ErrMsg(aktParser.lastErrNr, ref hilfStr); // Fehlerposition anzeigen mit ^ hilfStr = string.Concat("^ ", hilfStr); for (int i = 1; i <= aktParser.lastErrPos; i++) { hilfStr = string.Concat(" ", hilfStr); } this.textBoxErgebnis.Text = hilfStr; } else { if (this.art == TRechnerArt.formelRechner) { this.buttonFertig.IsEnabled = true; this.textBoxErgebnis.Text = string.Empty; } else { var wert = aktParser.FktWert_Berechne(this.scannedFkt, -1); this.textBoxErgebnis.Text = wert.ToString(CultureInfo.InvariantCulture); } } }
/// <summary> /// The get funktion. /// </summary> /// <returns> The <see cref="CalculatorFunctionTerm" /> . </returns> public FunctionCalcTree GetFunktion() { if (this.scannedFkt != null) { this.Ergebnis = this.textBox1.Text; this.scannedFkt.Name = this.Ergebnis; } else { this.scannedFkt = null; } return(this.scannedFkt); }
/// <summary> /// Method of the Scanfkt: get expression. /// expression is a sum of terms or a term /// </summary> /// <param name="expr"> /// The expression /// </param> public void ScanFkt_Expression(ref FunctionCalcTree expr) { symTyp addop; FunctionCalcTree temp = null; if ((this.sym == symTyp.plus) || (this.sym == symTyp.minus)) { addop = this.sym; this.ScanFkt_GetSym(); } else { addop = symTyp.plus; } this.ScanFkt_Expression_Term(ref expr); if (addop == symTyp.minus) { if ((expr != null) && (expr.Cwert == symTyp.istZahl)) { expr = this.ScanFkt_Zahl(-expr.Zwert); } else { expr = this.ScanFkt_MakeNode(this.ScanFkt_Zahl(-1), symTyp.mal, expr); } } while ((this.sym == symTyp.plus) || (this.sym == symTyp.minus)) { do { addop = this.sym; this.ScanFkt_GetSym(); if (this.sym == symTyp.plus) { this.sym = addop; } else if ((this.sym == symTyp.minus) && (addop == symTyp.minus)) { this.sym = symTyp.plus; } }while (!((this.sym != symTyp.plus) && (this.sym != symTyp.minus))); this.ScanFkt_Expression_Term(ref temp); if (!this.fehler) { expr = this.ScanFkt_MakeNode(expr, addop, temp); } } }
/// <summary> /// Method of the Scanfkt: get functionterm. /// a functionterm is function or a factor /// </summary> /// <param name="fterm"> /// fterm - the functionterm. /// </param> public void ScanFkt_Expression_Term_FuncTerm(ref FunctionCalcTree fterm) { symTyp fsym; FunctionCalcTree temp = null; if (this.sym < symTyp.sinf) { this.ScanFkt_Expression_Term_FuncTerm_Faktor(ref fterm); } else if (this.sym == symTyp.fstrEnd) { this.ScanFkt_Err(4); } else { fterm = null; } while ((symTyp.pot <= this.sym) && (this.sym < symTyp.ffmax)) { fsym = this.sym; this.ScanFkt_GetSym(); if (fsym > symTyp.pot) { if (this.sym != symTyp.lklammer) { this.ScanFkt_Err(1); return; } } if (this.sym < symTyp.sinf) { this.ScanFkt_Expression_Term_FuncTerm_Faktor(ref temp); } else { this.ScanFkt_Expression_Term_FuncTerm(ref temp); } if (!this.fehler) { fterm = this.ScanFkt_MakeNode(fterm, fsym, temp); } } }
/// <summary> /// Method of the Scanfkt: get term. /// a term is a product or functionterm /// </summary> /// <param name="prod"> /// prod - the term. /// </param> public void ScanFkt_Expression_Term(ref FunctionCalcTree prod) { symTyp pSym; FunctionCalcTree temp = null; this.ScanFkt_Expression_Term_FuncTerm(ref prod); while ((this.sym == symTyp.mal) || (this.sym == symTyp.durch)) { pSym = this.sym; this.ScanFkt_GetSym(); this.ScanFkt_Expression_Term_FuncTerm(ref temp); if (!this.fehler) { prod = this.ScanFkt_MakeNode(prod, pSym, temp); } } }
/// <summary> /// Method of the Scanfkt: get factor. /// a factor is a variable, a constant, a number or an expression /// </summary> /// <param name="fakt"> /// fakt - the factor. /// </param> public void ScanFkt_Expression_Term_FuncTerm_Faktor(ref FunctionCalcTree fakt) { if (this.fehler) { return; } switch (this.sym) { case symTyp.ident: fakt = this.xVar; break; case symTyp.istKonst: fakt = this.kVar; break; case symTyp.istZahl: fakt = this.ScanFkt_Zahl(this.wert); break; case symTyp.lklammer: this.ScanFkt_GetSym(); this.ScanFkt_Expression(ref fakt); if (this.sym != symTyp.rklammer) { this.ScanFkt_Err(2); return; } break; default: this.ScanFkt_Err(4); return; // break; } this.ScanFkt_GetSym(); if (this.sym < symTyp.lklammer) { this.ScanFkt_Err(3); } }
/// <summary> /// Tests, if the function term contains no vars / only numbers and constants. /// </summary> /// <param name="fx"> /// fx - the function term to test. /// </param> /// <returns> /// The <see cref="bool"/> . /// </returns> private bool doesContainNoVar(FunctionCalcTree fx) { if ((fx == null) || (fx.Cwert <= symTyp.istKonst)) { return(true); } else { if (fx.Cwert == symTyp.ident) { return(false); } else { return(this.doesContainNoVar(fx.Li) && this.doesContainNoVar(fx.Re)); } } }
/// <summary> /// Tests, if the given function is a linear function. /// </summary> /// <param name="fx"> /// fx - the function term to test. /// </param> /// <returns> /// The <see cref="bool"/> . /// </returns> public bool isLinearFunction(FunctionCalcTree fx) { if ((fx == null) || (fx.Cwert <= symTyp.istKonst)) { return(true); } if (fx.Cwert > symTyp.pot) { return(this.doesContainNoVar(fx.Re)); } switch (fx.Cwert) { case symTyp.ident: return(true); case symTyp.pot: return(this.doesContainNoVar(fx.Li) && this.doesContainNoVar(fx.Re)); case symTyp.plus: return(this.isLinearFunction(fx.Li) && this.isLinearFunction(fx.Re)); case symTyp.minus: return(this.isLinearFunction(fx.Li) && this.isLinearFunction(fx.Re)); case symTyp.mal: return((this.doesContainNoVar(fx.Li) && this.isLinearFunction(fx.Re)) || (this.isLinearFunction(fx.Li) && this.doesContainNoVar(fx.Re))); case symTyp.durch: return(this.isLinearFunction(fx.Li) && this.doesContainNoVar(fx.Re)); default: return(false); } }
/// <summary> /// Method of FktWert: calculate value. /// </summary> /// <param name="fx"> /// function /// </param> /// <param name="nr"> /// The nr. /// </param> /// <returns> /// value <see cref="double"/> . /// </returns> public double FktWert_Berechne(FunctionCalcTree fx, int nr) { double erg2; if (this.fktWertError) { this.result = Constants.fehlerZahl; return(this.result); } switch (fx.Cwert) { case symTyp.istZahl: this.result = fx.Zwert; break; case symTyp.istKonst: this.result = fx.Zwert; break; case symTyp.ident: this.result = this.varXwert; break; default: erg2 = this.FktWert_Berechne(fx.Re, nr); if (this.fktWertError) { this.result = erg2; return(this.result); } if (fx.Cwert <= symTyp.pot) { this.erg1 = this.FktWert_Berechne(fx.Li, nr); if (this.fktWertError) { this.result = this.erg1; return(this.result); } switch (fx.Cwert) { case symTyp.plus: this.erg1 = this.erg1 + erg2; break; case symTyp.minus: this.erg1 = this.erg1 - erg2; break; case symTyp.mal: this.erg1 = this.erg1 * erg2; break; case symTyp.durch: if (erg2 != 0) { this.erg1 = this.erg1 / erg2; } else { this.FktWert_Berechne_Fehler(); } break; case symTyp.pot: if (Convert.ToInt16(erg2) == erg2) { this.erg1 = this.FktWert_WertIntPot(this.erg1, Convert.ToInt16(erg2)); } else if (this.erg1 > 0) { this.erg1 = Math.Exp(erg2 * Math.Log(this.erg1)); } else if (this.erg1 < 0) { this.FktWert_Berechne_Fehler(); } break; default: this.FktWert_Berechne_Fehler(); break; } } else { switch (fx.Cwert) { case symTyp.sinf: this.erg1 = Math.Sin(erg2); break; case symTyp.cosf: this.erg1 = Math.Cos(erg2); break; case symTyp.tanf: this.erg1 = Math.Cos(erg2); if (this.erg1 != 0) { this.erg1 = Math.Sin(erg2) / this.erg1; } else { this.FktWert_Berechne_Fehler(); } break; case symTyp.ctgf: this.erg1 = Math.Sin(erg2); if (this.erg1 != 0) { this.erg1 = Math.Cos(erg2) / this.erg1; } else { this.FktWert_Berechne_Fehler(); } break; case symTyp.expf: this.erg1 = Math.Exp(erg2); break; case symTyp.lnf: if (erg2 > 0) { this.erg1 = Math.Log(erg2); } else { this.FktWert_Berechne_Fehler(); } break; case symTyp.wurzf: if (erg2 >= 0) { this.erg1 = Math.Sqrt(erg2); } else { this.FktWert_Berechne_Fehler(); } break; case symTyp.sigf: if (erg2 > 0) { this.erg1 = 1; } else if (erg2 < 0) { this.erg1 = -1; } else { this.erg1 = 0; } break; case symTyp.absf: this.erg1 = Math.Abs(erg2); break; case symTyp.deltaf: if (nr == 0) { this.erg1 = Constants.leerFeld; } else { this.erg1 = this.FktWert_Berechne(fx.Re, nr - 1); if (this.fktWertError) { this.result = this.erg1; return(this.result); } this.erg1 = erg2 - this.erg1; } break; default: this.FktWert_Berechne_Fehler(); break; } } this.result = this.erg1; break; } return(this.result); }