ã³ã³ãã¥ãŒã¿ãŒãšäººé-ç§ãã¡ããäºããç解ããããšã¯ã©ãã»ã©é£ãããã å®éãããã°ã©ãã³ã°ããã»ã¹ã¯ããã·ã³ãç解ã§ããèšèªã§ããã·ã³ã«å¿ èŠãªãã®ã説æãããã®ã§ãã
ã¯ããã«
ç§ã®ä»äºã§ã¯ããŸã趣å³ãšããŠãæ°åŠèšç®ã«é¢é£ããã³ãŒããæžãããã»ã¹ã«é¢äžããŠããŸãã æåŸã®ã¿ã¹ã¯ã®1ã€ã¯ãããŒã¿ãèšç®ãèŠèŠåãããã³ããã€ãã®æ°åŒãæé©åãããšãã«ããŠãŒã¶ãŒãç¬èªã«å ¥åããŠäœ¿çšã§ãããœãããŠã§ã¢ãäœæããããšã§ããã ãããŠãç¹å¥ãªæ°åŠé¢æ°ã®ã³ãŒãã©ã€ãã©ãªã絶ããè£å®ããç§ã®èªç¶ãªæ andããšäžæ¬æãèæ ®ããŠãèããæãæµ®ãã³ãŸãã-ã¯ã¬ã€ãžãŒãªåŠçã®ã¢ã€ãã¢ãå®è£ ããæ°åŒçšã®ããŒãµãŒãã€ã¯ãçºæããªãã®ã¯ãªãã§ããïŒ
ãã¡ãããæ¬çºæã®ããã»ã¹ã«çæããåã«ïŒåã³ãæ®éçãªæ inessãèæ ®ããŠïŒãæ¢åã®å®è£ ãããŒãã«ããYandexãšGoogleã®ããªãé·ãã¬ã€ãããããŸããã ãããŠãã¡ããã圌ãã¯éåžžã«å€ãçºèŠãããŸããã ããããæ®å¿µãªãããç¹å®ã®å®è£ ããéæãããã£ããã®ã¯èŠã€ãããŸããã§ããã æ€çŽ¢æ¡ä»¶ã¯æ¬¡ã®ãšããã§ãã
- ããŒãµãŒã¯ã4.0ããå€ã.NETã®äžã§å®è£ ããå¿ èŠããããŸãã
- ãã¹ãŠã®åºæ¬çãªæ°åŠæŒç®åïŒ+ã-ã*ã/ã^ãªã©ïŒãåŠçããããŸããŸãªçš®é¡ã®åªå é äœãšãã©ã±ãããèæ ®ã«å ¥ããå¿ èŠããããŸãã
- ã¡ã€ã³é¢æ°ïŒsinãcosãªã©ïŒãèªèããäœæãããããŒãµãŒãªããžã§ã¯ãã«ç¬èªã®é¢æ°ãè¿œå ããŠãïŒä»»æã®æ°ã®å ¥åå€æ°ã«å¯ŸããŠïŒå€ãèšç®ããã¡ãœããã®ããªã²ãŒãã瀺ãããšãã§ããŸãã
- ããŒãµãŒã«æ¢ç¥ã®å®æ°ã䜿çšããããããåŒã®è§£æã«äœ¿çšããããªã¹ãã«è¿œå ããããšãã§ããã¯ãã§ãã
- ãã©ã¡ãŒã¿ãšå€æ°ãæäœããã¡ã«ããºã ãå¿ èŠã§ãã ããã«ã¯ãããŸããŸãªã¿ã€ãã®å€æ°ãå¿ èŠã§ããåã«æ°å€ãæ ŒçŽããããåŒã³åºãæã«å€éšã³ãŒããå€ã決å®ããã€ãã³ããçºçãããŸãã
- æ©èœçãªã¡ã«ããºã ãå®è£ ããå¿ èŠããããŸãïŒæå°-çµ±åãã·ãªãŒãºã®åèšãããã³å·®å¥åïŒ
- æåååŒã®è§£æçµæã¯ããã€ããªããªãŒãªããžã§ã¯ãã¢ãã«ã§è¡šçŸããå¿ èŠããããŸãã
- æãéèŠãªããšã¯ããã€ããªããªãŒãLinq.ExpressionããªãŒã«ãããã§ããããã.NETãã©ãããã©ãŒã èªäœã®é床ã§èšç®ãå®è¡ããããªã²ãŒãã«ã³ã³ãã€ã«ã§ããããšã§ãã
èªè»¢è»äœãã®ç®æš
å®éãèªè»¢è»ã®çºæã®äž»ãªç®æšã¯ãäžé£ã®æ°åŒãããªã²ãŒãã«ã³ã³ãã€ã«ããŠãå€ãèšç®ããããã»ã¹ãé«éåããå¯èœæ§ã§ããã
æ®å¿µãªãããæ€çŽ¢ãšã³ãžã³ã§äœæ¥ããããã®ç§ã®ããããªèœåãæéãåŽåãæ ofã®æ¬ åŠã¯ããããã¿ã€ãã®æ€çŽ¢ã§è¯å®çãªçµæããããããªãã£ããããçææ è¡ã«çæããããšã«ããŸããã
ã¢ãã«ãšäž»ãªã¢ã€ãã¢
ãªããžã§ã¯ãã¢ãã«ã¯ãããŒãµãŒã¯ã©ã¹ãšæ°åŒã¯ã©ã¹ã®2ã€ã®ã¯ã©ã¹ã§æ§æãããŸãã å éšã§ã¯ãããã«3ã€ã®ã¯ã©ã¹ã䜿çšãããŸãïŒæ°åŠåŒããªãŒã¯ã©ã¹ãmat.expressionããªãŒã®æœè±¡ããŒãã¯ã©ã¹ãããã³mat.expressionæååã®è«çèŠçŽ ã®ã¯ã©ã¹-çšèªã ããã«ãé¢æ°ãå€æ°ãé¢æ°ã®ã¯ã©ã¹ãããã³é¢æ°ãå€æ°ãããã³é¢æ°ã®ã³ã¬ã¯ã·ã§ã³ãããããå®è£ ãããŸãïŒãããã¯æ°åŠã®ã¯ã©ã¹ã«åã蟌ãŸããŸãïŒã
çºèŠããŸãã¯è§£æ±ºçã®æé©åã®ãµããããŠããªãããåé¡ã®è§£æ±ºçã«ã¢ãããŒãããè©Šã¿ã§ãã£ãã¢ã€ãã¢ã¯ãmat.expressionæååã®æåã®åæã·ãŒã±ã³ã¹ãããã€ãã®è«çã³ã³ããŒãã³ãã«å解ããããšã§ããã åä»ããããæ°åŒã®è«çãããã¯ã®éå±€ã·ãŒã±ã³ã¹ã圢æããŸãã ãããŠãããã«åºã¥ããŠãmat.expressionã®ããªãŒãæ§ç¯ããŸãã
èšèšã¯ããã©ã®ããã«å®æãããŠã䜿ãããã䟿å©ã«ããããïŒããšããã¢ã€ãã¢ããå§ãŸããŸããã 次ã®ãŠãŒã¹ã±ãŒã¹ãå®è£ ããããšæããŸããã
ããŒãµãŒãªããžã§ã¯ããäœæããããã¬ãŒã³ããŒã·ã§ã³ã¢ãã«ã®ã¬ãã«ãŸãã¯ããžãã¹ããžãã¯ã®ã©ããã«ä¿®æ£ãããŸãã ããã¯æ§æãããŸãïŒå¿ èŠãªå®æ°ãããã«è¿œå ããããã®åŸæ©èœããé¢æ°ãå®çŸ©ãããŸãã äžæãªé¢æ°ããã³å€æ°ãåŠçããããã«ãã€ãã³ããµãã¹ã¯ã©ã€ããŒãè¿œå ãããŸãã ãããŠãããŒãµãŒã¯ParceïŒstringïŒã¡ãœããã®åŒã³åºããåŸ ã£ãŠããŸãã
ã¡ã€ã³ã®ParceïŒïŒã¡ãœããã§ã¯ããããåŒæååãå ¥åãšããŠæž¡ããããã®çµæã¯ãããåŒããªãŒãå«ããããåŒãªããžã§ã¯ãã«ãªããŸãã
mat.expressionã®ãªããžã§ã¯ãã«ã¯ããã®äžã«ããé¢æ°ãå€æ°ãããã³å®æ°ã®ã³ã¬ã¯ã·ã§ã³ãå¿ èŠã§ãã ãããã®ãªããžã§ã¯ãã®å€ãå€æŽããå¯èœæ§ãããã³ãã®ä¿®æ£ãç®çãšããŠåŒããªãŒã«åœ±é¿ãäžããå¯èœæ§ãããã¯ãã§ãã æ°åŒã®ãªããžã§ã¯ãã«ã¯ãïŒæ°åŒã®ããªãŒããã©ããŒã¹ããããšã«ããïŒå€ãèšç®ããã¡ãœãããå¿ èŠã§ãããã®ã¡ãœããã¯ãå ¥åå€æ°ã®ã»ããããã©ã¡ãŒã¿ãŒãšããŠåãåããçµæãšããŠæ°å€ãçæããŸãã
æ°åŒãªããžã§ã¯ãã«ã¯ãæ°åŒããªãŒãSystem.Linq.Expressionãªããžã§ã¯ãã«å€æããã¡ãœãããå¿ èŠã§ãã ãããŠãLinq.Expressionã¡ã«ããºã ã䜿çšããŠããã«ã³ã³ãã€ã«ãããããªã²ãŒããååŸããã¡ãœããã
æ®å¿µãªãããé¡äŒŒããäœãã®æ¢è£œã®å®è£ ãããã®ãããªããŒãµãŒã®äœæãããçšåºŠèª¬æããæ¹æ³ããã©ãã«ã説æãããŠããŸããã
ãªããžã§ã¯ãã¢ãã«ã®èª¬æ
ããŒãµãŒã¯ã©ã¹
ãªããžã§ã¯ãã®äœæïŒäœæåŸïŒã¯ãParseã¡ãœããã®åŒã³åºãããå§ãŸããŸãã
ãããªãã¯MathExpression解æïŒæååStrExpressionïŒ
å¥çŽãçç¥ãããšã圌ã®ä»äºã®æå³ã¯ãæååã®ååŠçãæ°åŒã®ã³ã³ã¹ãã©ã¯ã¿ãŒã®åŒã³åºããããã³å€æ°ãšé¢æ°ã®åæã®ããã®ãã®åŒã®åŸåŠçã«éå®ãããŸãã
/// <summary> </summary> /// <param name="StrExpression"> </param> /// <returns> </returns> [NotNull] public MathExpression Parse([NotNull] string StrExpression) { Contract.Requires(!string.IsNullOrWhiteSpace(StrExpression)); Contract.Ensures(Contract.Result<MathExpression>() != null); StrPreprocessing(ref StrExpression); OnStringPreprocessing(ref StrExpression); var expression = new MathExpression(StrExpression, this); ProcessVariables(expression); ProcessFunctions(expression); return expression; }
å¥çŽãçç¥ãããšã圌ã®ä»äºã®æå³ã¯ãæååã®ååŠçãæ°åŒã®ã³ã³ã¹ãã©ã¯ã¿ãŒã®åŒã³åºããããã³å€æ°ãšé¢æ°ã®åæã®ããã®ãã®åŒã®åŸåŠçã«éå®ãããŸãã
ååŠçã«ã¯2ã€ã®æ®µéããããŸãã
æååããäœåãªæåãåé€ãããã©ã€ããŒãStrPreprocessingã¡ãœããïŒ
ä¿è·ãããvoid StrPreprocessingïŒåç
§æååStrïŒ
/// <summary> </summary> /// <param name="Str"> </param> // , protected virtual void StrPreprocessing([NotNull] ref string Str) { Contract.Requires(!string.IsNullOrEmpty(Str)); Contract.Ensures(!string.IsNullOrEmpty(Contract.ValueAtReturn(out Str))); Str = new string(Str.Where(f_ExcludeCharsSet.NotContains).ToArray()); }
ããŒãµãŒãŠãŒã¶ãŒãåæã®ããã«æååãç¬ç«ããŠæºåã§ããããã«ãæååååŠçã€ãã³ããçæããã¡ãœããïŒ
ãããªãã¯ã€ãã³ãEventHandler <EventArgs <string >> StringPreprocessing
/// <summary> </summary> public event EventHandler<EventArgs<string>> StringPreprocessing; /// <summary> </summary> /// <param name="args"> , </param> protected virtual void OnStringPreprocessing([NotNull] EventArgs<string> args) { Contract.Requires(args != null); Contract.Requires(args.Argument != null); Contract.Requires(args.Argument != string.Empty); Contract.Ensures(args.Argument != null); Contract.Ensures(args.Argument != string.Empty); StringPreprocessing?.Invoke(this, args); } /// <summary> </summary> /// <param name="StrExpression"> </param> private void OnStringPreprocessing([NotNull] ref string StrExpression) { Contract.Requires(!string.IsNullOrEmpty(StrExpression)); Contract.Ensures(Contract.ValueAtReturn(out StrExpression) != null); Contract.Ensures(Contract.ValueAtReturn(out StrExpression) != string.Empty); var args = new EventArgs<string>(StrExpression); OnStringPreprocessing(args); StrExpression = args.Argument; }
è¡ã®ã¬ããŒãžãã¯ãªã¢ããã解æã®æºåãæŽããšãåŒã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãããŸãã é¢æ°ãå®æ°ãå€æ°ã®å®çŸ©ãæ åœããããŒãµãŒèªäœãæž¡ãããŸãã
ãã®ã¡ã³ããŒãèšåããããšãããŒãµãŒã¯ã©ã¹ã«æ»ããŸãããããŠã...æ°åŠè¡šçŸã®ã¯ã©ã¹ïŒ
ãã£ãŒã
Parseã¡ãœããããã®åŒã³åºããæž¡ãããã³ã³ã¹ãã©ã¯ã¿ãŒïŒ
å
éšMathExpressionïŒæååStrExpressionãExpressionParserããŒãµãŒïŒ
/// <summary> </summary> /// <param name="StrExpression"> </param> /// <param name="Parser"> </param> internal MathExpression([NotNull] string StrExpression, [NotNull] ExpressionParser Parser) : this() { Contract.Requires(!string.IsNullOrEmpty(StrExpression)); Contract.Requires(Parser != null); Contract.Ensures(Tree != null); var terms = new BlockTerm(StrExpression); // var root = terms.GetSubTree(Parser, this); // f_ExpressionTree = new ExpressionTree(root); // }
ç¹°ãè¿ããŸãããã³ã³ãã©ã¯ããããã¯ãçç¥ãããšãæåã«ãè¡ã«åºã¥ããŠãåŒã®çšèªã®éå±€ãªããžã§ã¯ãæ§é ãäœæãããŸãã 次ã«ãæåã®ãããã¯ãããmat.expressionã®ããªãŒã®ã«ãŒããååŸããã¡ãœãããåŒã³åºãããŸãã ãããŠãããã«åºã¥ããŠããªãŒã³ã³ã¹ãã©ã¯ã¿ãŒãæ©èœããŸãã
æ°åŒã®åæã®æåã®æ®µéã§ã¯ãæååè¡šçŸïŒæåã®ã·ãŒã±ã³ã¹ïŒãè«çãããã¯ã®ã·ãŒã±ã³ã¹ã«çµåããå¿ èŠããããŸãã ãããã®ããã€ãã¯ãäºãã«ååž°çã«ãã¹ãã§ããŸãã
åŒçšèªã¯ã©ã¹ã®éå±€
è¡ã¯4çš®é¡ã®çšèªã«åãããŠããŸãã
- BlockTerm-çšèªã®é åãå«ãçšèªã
- StringTerm-æååå€ãå«ãçšèª
- CharTerm-éåžžã®æååã«é¢é£ä»ããããšãã§ããªã1æåãå«ãçšèªã
- NumberTermã¯ãæŽæ°ãå«ãçšèªã§ãã
ãããã£ãŠãæåã¯è¡å šäœã1ã€ã®ãããã¯çšèªãšããŠè¡šããããã®äžã«æ§æèŠçŽ ãå«ãŸããŸãã
public BlockTermïŒæååStrïŒ
/// <summary> </summary> /// <param name="Str"> </param> public BlockTerm(string Str) : this("", Str, "") { } /// <summary> </summary> /// <param name="OpenBracket"> </param> /// <param name="Str"> </param> /// <param name="CloseBracket"> </param> public BlockTerm([NotNull] string OpenBracket, [NotNull] string Str, [NotNull] string CloseBracket) : base(string.Format("{0}{2}{1}", OpenBracket ?? "", CloseBracket ?? "", Str)) { Contract.Requires(!string.IsNullOrEmpty(Str)); f_OpenBracket = OpenBracket; f_CloseBracket = CloseBracket; f_Terms = GetTerms(Str); }
åºæ¬çãªãã«ãã¯ã©ã¹ïŒ
æœè±¡ã¯ã©ã¹Term {...}
/// <summary> </summary> abstract class Term { /// <summary> </summary> protected string f_Value; /// <summary> </summary> /// <param name="Value"> </param> protected Term(string Value) { f_Value = Value; } /// <summary> </summary> /// <param name="Parser"> </param> /// <param name="Expression"> </param> /// <returns> ., </returns> [NotNull] public abstract ExpressionTreeNode GetSubTree([NotNull] ExpressionParser Parser, [NotNull] MathExpression Expression); /// <summary> .</summary> /// <returns> .</returns> public override string ToString() => f_Value; }
éšåæååã®æ§æèŠçŽ ãžã®å èš³ã¯ãGetTermsã¡ãœããã«ãã£ãŠå®è¡ãããŸãã
private static Term [] GetTermsïŒæååStrïŒ
/// <summary> </summary> /// <param name="Str"> </param> /// <returns> </returns> [CanBeNull] private static Term[] GetTerms([CanBeNull] string Str) { if(Str == null) return null; if(Str.Length == 0) return new Term[0]; var pos = 0; var len = Str.Length; var result = new List<Term>(); while(pos < len) { var c = Str[pos]; if(char.IsLetter(c) || c == 'â«') { Term value = new StringTerm(GetNameString(Str, ref pos)); if(pos < len) switch(Str[pos]) { case '(': { var blokStr = Str.GetBracketText(ref pos); var block = new BlockTerm("(", blokStr, ")"); value = new FunctionTerm((StringTerm)value, block); } break; case '[': { var blokStr = Str.GetBracketText(ref pos, "[", "]"); var block = new BlockTerm("[", blokStr, "]"); value = new FunctionTerm((StringTerm)value, block); } break; case '{': { var blokStr = Str.GetBracketText(ref pos, "{", "}"); var block = new BlockTerm("{", blokStr, "}"); value = new FunctionTerm((StringTerm)value, block); } break; } if(pos < len && Str[pos] == '{') value = new FunctionalTerm ( (FunctionTerm)value, new BlockTerm("{", Str.GetBracketText(ref pos, "{", "}"), "}") ); result.Add(value); } else if(char.IsDigit(c)) result.Add(new NumberTerm(GetNumberString(Str, ref pos))); else switch(c) { case '(': { var blokStr = Str.GetBracketText(ref pos); var block = new BlockTerm("(", blokStr, ")"); result.Add(block); } break; case '[': { var blokStr = Str.GetBracketText(ref pos, "[", "]"); var block = new BlockTerm("[", blokStr, "]"); result.Add(block); } break; case '{': { var blokStr = Str.GetBracketText(ref pos, "{", "}"); var block = new BlockTerm("{", blokStr, "}"); result.Add(block); } break; default: result.Add(new CharTerm(Str[pos++])); break; } } return result.ToArray(); }
ãã®ã¡ãœããã¯ã空ã®å ¥åè¡ãšãŒãé·ããã§ãã¯ããããšããå§ãŸããŸãã ãã®åŸãè¡å ã®åæãããã·ã³ãã«ã®çŸåšã®äœçœ®ãšãã®é·ããåºå®ããããã®åŸãçŸåšã®äœçœ®ã®ã·ã³ãã«ã¯è¡ã®çµããã«éãããŸã§ãµã€ã¯ã«ã§èæ ®ãããŸãã
-æåãŸãã¯æŽæ°ã®èšå·ã®å ŽåãGetNameStringã¡ãœããã䜿çšããŠååããã£ããã£ããããšããŸãã
ãã©ã€ããŒãéçæååGetNameStringïŒæååStrãref int posïŒ
/// <summary> </summary> /// <param name="Str"> </param> /// <param name="pos"> </param> /// <returns> </returns> private static string GetNameString([NotNull] string Str, ref int pos) { Contract.Requires(!string.IsNullOrEmpty(Str)); Contract.Ensures(Contract.ValueAtReturn(out pos) >= 0); Contract.Ensures(Contract.ValueAtReturn(out pos) < Str.Length); var result = ""; var L = Str.Length; var i = pos; while(i < L && (char.IsLetter(Str[i]) || Str[i] == 'â«')) result += Str[i++]; if(i == L || !char.IsDigit(Str[i])) { pos = i; return result; } while(i < L && char.IsDigit(Str[i])) result += Str[i++]; pos += result.Length; return result; }
ãã®åŸãçŸåšã®æåã«éå§ãã©ã±ããããããã©ããããã§ãã¯ãããŸãã ãã©ã±ããã®1ã€ãèŠã€ãã£ãå Žåããã¹ãããããããã¯ãè¡ããæœåºãããéå§ãã©ã±ãããšå¯Ÿå¿ããçµäºãã©ã±ããã«ãã£ãŠå¶éãããŸãã ãã®æ¹æ³ã§äœæããããããã¯çšèªã¯ãæ©èœçšèªã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«é 眮ãããåã«èšå®ãããé¢æ°åã瀺ãããŸãã
éãæ¬åŒ§ãšéãæ¬åŒ§ã§å¶éãããéšåæååã¯ãæ¡åŒµã¡ãœããã«ãã£ãŠæååããéžæãããŸãã
public static string GetBracketTextïŒãã®æååStrãref int OffsetãæååOpenãæååCloseïŒ
/// <summary> /// , /// </summary> /// <param name="Str"> </param> /// <param name="Offset"> /// - /// </param> /// <param name="Open"> </param> /// <param name="Close"> </param> /// <returns>, </returns> /// <exception cref="FormatException"> /// , /// /// </exception> public static string GetBracketText(this string Str, ref int Offset, string Open = "(", string Close = ")") { var Start = Str.IndexOf(Open, Offset, StringComparison.Ordinal); if(Start == -1) return null; var Stop = Str.IndexOf(Close, Start + 1, StringComparison.Ordinal); if(Stop == -1) throw new FormatException(); var start = Start; do { start = Str.IndexOf(Open, start + 1, StringComparison.Ordinal); if(start != -1 && start < Stop) Stop = Str.IndexOf(Close, Stop + 1, StringComparison.Ordinal); } while(start != -1 && start < Stop); if(Stop == -1 || Stop < Start) throw new FormatException(); Offset = Stop + Close.Length; Start += Open.Length; return Str.Substring(Start, Stop - Start); }
æåã«ãéå§æåãšçµäºæåã®æåã®åºçŸã®ã€ã³ããã¯ã¹ã決å®ãããŸãã æåã®æåãèŠã€ãããªãå Žåã¯ãvoidãè¿ããŸãã çµäºæåãèŠã€ãããªãå Žåãããã¯ãã©ãŒããããšã©ãŒã§ãã
ãã®æ¹æ³ã®èãæ¹ã¯ãè¡ã®å é ãšæ«å°Ÿã®ãã¿ãŒã³ãé çªã«åŸªç°æ€çŽ¢ããããšã§ãã 次ã®ãªãŒããã³ã°ãã£ã©ã¯ã¿ãŒãèŠã€ããããšããŠããŸãã èŠã€ãã£ãŠãçµäºæåã®åã«ããå Žåã¯ãçµäºæåã®ã€ã³ããã¯ã¹ãæŽæ°ããå¿ èŠããããŸãã ãµã€ã¯ã«ã¯ãéå§æåã®åã«ãªãçµäºæåããããŸã§ç¶ããŸãã
ã¡ãœããã®çµæã¯ãéå§æåãšçµäºæåã®éã«ãããµãã¹ããªã³ã°ã§ãã
圢æãããæ©èœçšèªã®åŸã«éå§äžæ¬åŒ§ãèŠã€ãã£ãå Žåãããã¯æ©èœã®æ¬äœãéå§ããŸãã ãããã¯å ã®äžæ¬åŒ§ã®å 容ãéžæããterm-functionalãäœæããterm-functionã瀺ããŸãããã®ã³ã³ããã¹ãã§ã¯ãé¢æ°ã®ååãšãã®ãã©ã¡ãŒã¿ãŒãå«ãŸããæ¬äœã¯äžæ¬åŒ§å ã®ãããã¯ã«ãªããŸãã
æ¬åŒ§ãèŠã€ãããªãã£ãå ŽåãèŠã€ãã£ãååã¯ãªãã©ã«ïŒå°æ¥ã®å€æ°...ãŸãã¯å®æ°ïŒã§ãã
-æååã®æ¬¡ã®æåãæ°åã®å ŽåãæŽæ°ãå§ãŸããŸãã æ°åã®ã¿ãå«ãéšåæååãéžæããŸãã
ãã©ã€ããŒãéçæååGetNumberStringïŒæååStrãref int posïŒ
/// <summary> </summary> /// <param name="Str"> </param> /// <param name="pos"> </param> /// <returns> </returns> private static string GetNumberString([NotNull] string Str, ref int pos) { Contract.Requires(!string.IsNullOrEmpty(Str)); Contract.Ensures(Contract.ValueAtReturn(out pos) >= 0); Contract.Ensures(Contract.ValueAtReturn(out pos) < Str.Length); var p = pos; var l = Str.Length; while(p < l && !char.IsDigit(Str, p)) p++; if(p >= l) return null; var start = p; while(p < l && char.IsDigit(Str, p)) p++; pos = p; return Str.Substring(start, p - start); }
ãã®ã¡ãœããã®çµæ-æ°åãå«ãæåå-ã¯ãæŽæ°é ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«åé¡ãããŸãã
-è¡ã®æ¬¡ã®æåãéãæ¬åŒ§ã®å Žåããããã¯ãå§ãŸããŸãã GetBracketTextæ¡åŒµã¡ãœããã§ãã®ãµãã¹ããªã³ã°ãéžæããŸãã
-次ã®æåããã©ã±ããã§ã¯ãªãå Žåãããã¯ã·ã³ãã«çšèªã«å€ããæªå®çŸ©ã®æåã§ãã
äœæããããã¹ãŠã®çšèªã¯æåã«ãªã¹ãããåéãããé åãšããŠè¿ãããŸãã
ä»ã®ãã¹ãŠã®çšèªã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ããã»ã©é¢çœããããŸããã ãããã¯ãçµæã®ãã©ã¡ãŒã¿ãŒãå éšãã£ãŒã«ãã«æ ŒçŽããã ãã§ãïŒããããåå€æã䜿çšïŒã
ãã®åŸãæååã¯ãäºãã«åã蟌ãŸããç°ãªãã¿ã€ãã®çšèªã®ã·ãŒã±ã³ã¹ã®è«ççãªéå±€æ§é ã«å€æãããŸãã ãã®ã·ãŒã±ã³ã¹ãããæ°åŒã®äºåæšãååž°çã«æ§ç¯ãããŸãã
ããªãŒã®åºç€ã¯ããããã®ããªãŒããŒãã®åºæ¬ã¯ã©ã¹ã§ãã
ã¯ã©ã¹éå±€
åããŒãã¯ãå·Šã®ãµãããªãŒã®ã«ãŒãããŒããšå³ã®ãµãããªãŒã®ã«ãŒãããŒããžã®ãªã³ã¯ãããã³ãã®ç¥å ãžã®ãªã³ã¯ãæ ŒçŽããã¯ã©ã¹ã§ãã ããªãŒããŒãã®æœè±¡ã¯ã©ã¹ã¯ãç¥å /åå«ã®ããŒãããã©ããŒãµã«ã¡ãœãããçŸåšã®ããŒãã«é¢é£ä»ããããŠããããŒãã®åæãååŸã§ããæ©èœã€ã³ãã¯ãµãŒããã®ããŒãã«ïŒãµãããªãŒã®ã«ãŒããšããŠïŒæ¢ç¥ã®å€æ°ãé¢æ°ãªã©ãååŸããããã®ååž°ã¡ãœããã«ã¢ã¯ã»ã¹ããããã®ã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããŸãã ãŸããããŒãã®åºæ¬ã¯ã©ã¹ã¯ãå€ãã®èšç®å¯èœãªããããã£ãæäŸããŸãïŒãµã€ã³-ããŒããå·Š/å³ãµãããªãŒã§ãããã©ãããããŒããã«ãŒãã§ãããã©ãããããªãŒã«ãŒããžã®ãªã³ã¯ãããªãŒã«ãŒãããçŸåšã®ããŒããžã®ã·ã³ããªãã¯ãã¹ãããã³ç¥å ã€ãã¬ãŒã¿ã
æšã®çµã³ç®
ãã®ã¯ã©ã¹ã®ã³ãŒãã«ãããããªãŒèŠçŽ ã䜿çšããåºæ¬çãªæäœãå¯èœã«ãªãããããã眮æãåé 眮ããã©ããŒã¹ãããã³ã¢ã¯ã»ã¹ã§ããŸãã å¿ èŠã«å¿ããŠåå¥ã®ã¡ãœãããæäŸããŸãã å šæã¯å€ãã®ã¹ããŒã¹ãå æããŸãã ãããžã§ã¯ããœãŒã¹ãã衚瀺/ã³ããŒã§ããŸãã
ããªãŒã®ãã¹ãŠã®ããŒãã¯ãèšç®å¯èœãŸãã¯è§£æã§äœ¿çšã§ããŸãã
解æããŒãã«ã¯ãæååããŒããæåããŒããééå€ããŒããå«ãŸããŸãã ãããã¯ãééãæå®ããå¿ èŠãããçµ±åæ©èœãªã©ãããªãŒå ã®ç¹å®ã®ã¡ã¿æ§é ãè£å®ããããã«å¿ èŠã§ãã
èšç®å¯èœãªããŒãã¯ãçµæã®ããªãŒæ§é ã®äž»èŠãªããŒãã§ãã ãããã¯ãæ°åŒã§èšè¿°ã§ãããã¹ãŠã®èŠçŽ ãè¡šããŸãã
ãããã«ã¯ä»¥äžãå«ãŸããŸãã
- ComputedBracketNode-ãã©ã±ããã®ãããã¯ãè¡šããŸã
- ValueNodeã¯ãå€ããŒããè¡šãæœè±¡ã¯ã©ã¹ã§ãã 圌ã®çžç¶äººïŒ
-ConstValueNode-æ°å€ããŒã
-VariableValueNode-å€æ°ããŒãïŒpiãeã...ãªã©ã®å®æ°ïŒ
- FunctionNode-é¢æ°ãªããžã§ã¯ããè¡šãããŒã
- FunctionalNode-æ©èœãªããžã§ã¯ããè¡šãããŒã
- NodeæŒç®åã¯ãæŒç®åããŒãã®æœè±¡ã¯ã©ã¹ã§ãã 圌ã®çžç¶äºº
-æãåçŽãªæ°åŠæŒç®å+ã-ã*ã/ã^;
-è«çæŒç®å==ãïŒã>ã<ã&&ã||;
-æ¡ä»¶ã<è«çæŒç®åã®æŒç®çµæ>ïŒãã®æŒç®å ãããŠãéžææŒç®åã<option_1>ïŒ<option_2>ã
-é¢æ°ã®åŒæ°ãžã®ã¢ã¯ã»ã¹ãå®è£ ããæŒç®åãšãé¢æ°ã®åŒæ°ã®ååã«ã¢ã¯ã»ã¹ããããã«äœ¿çšãããã¹ããŒãã¡ã³ãã
ããªãŒæ§ç¯ããã»ã¹
çšèªã¯ã©ã¹ã¯æœè±¡ã¡ãœããGetSubTreeã宣èšããŸããããã«ãããä»»æã®çšèªããããã«ãã£ãŠèšè¿°ããããµãããªãŒãååŸã§ããŸãã ããªãŒã®æ§ç¯ããã»ã¹ã¯ããœãŒã¹æååããçæããããããã¯çšèªã§ãã®ã¡ãœãããåŒã³åºãããšããå§ãŸããŸãã
ãããªãã¯ãªãŒããŒã©ã€ãExpressionTreeNode GetSubTreeïŒExpressionParserããŒãµãŒãMathExpression ExpressionïŒ
/// <summary> </summary> /// <param name="Parser"> </param> /// <param name="Expression"> </param> /// <returns> </returns> public override ExpressionTreeNode GetSubTree(ExpressionParser Parser, MathExpression Expression) { Contract.Requires(Parser != null); Contract.Requires(Expression != null); Contract.Ensures(Contract.Result<ExpressionTreeNode>() != null); var separator = Parser.ExpressionSeparator; // - // , - // var roots = Terms .Split(t => t is CharTerm && ((CharTerm)t).Value == separator) .Select(g => Parser.GetRoot(g, Expression)).ToArray(); if(roots.Length == 1) return roots[0]; // , // ExpressionTreeNode argument = null; // for(var i = 0; i < roots.Length; i++) // { var root = roots[i]; ExpressionTreeNode arg; // if(root is FunctionArgumentNode) // - arg = root; // -- else if(root is FunctionArgumentNameNode) // - // -- arg = new FunctionArgumentNode(root as FunctionArgumentNameNode); else if(root is VariantOperatorNode && root.Left is VariableValueNode) arg = new FunctionArgumentNode(((VariableValueNode)root.Left).Name, root.Right); else // - arg = new FunctionArgumentNode("", root); // -- if(argument == null) argument = arg; // , , else // argument = argument.Right = arg; // } // , - - if(argument == null) throw new FormatException(" "); return argument.Root; // }
ãã®ã¡ãœããã¯ãæž¡ããããªããžã§ã¯ãããããããã¯å ã®åŒãè¡šãã·ã³ãã«ãæœåºããŸãã ããã©ã«ãã®åºåãæåã¯ã;ãã§ãã -ã»ãã³ãã³ã
次ã«ãLinqã·ãŒã±ã³ã¹ã§ã¯ããã¹ããããçšèªã®é åå šäœããã»ãã¬ãŒã¿ïŒåŒã®åºåãæåãå«ãã·ã³ããªãã¯çšèªïŒã«ãã£ãŠãµãé åã«åå²ãããŸãã ããã¯ãSplitæ¡åŒµã¡ãœãããæ åœããŸãã
public static T [] [] Split <T>ïŒãã®T []é
åãFunc <Tãbool>ã¹ããªãã¿ãŒïŒ
/// <summary> </summary> /// <typeparam name="T"> </typeparam> /// <param name="array"> </param> /// <param name="Splitter">, , </param> /// <returns> /// , . /// . /// </returns> [NotNull] public static T[][] Split<T>([NotNull] this T[] array, [NotNull] Func<T, bool> Splitter) { Contract.Requires(array != null); Contract.Requires(Splitter != null); Contract.Ensures(Contract.Result<T[][]>() != null); var result = new List<T[]>(array.Length); var aggregator = new List<T>(array.Length); for(var i = 0; i < array.Length; i++) { var value = array[i]; if(Splitter(value) && aggregator.Count != 0) { result.Add(aggregator.ToArray()); aggregator.Clear(); } else aggregator.Add(value); } if(aggregator.Count != 0) result.Add(aggregator.ToArray()); return result.ToArray(); }
çšèªã®ãµãé åããšã«ããã®ã°ã«ãŒãã®çšèªã®ããªãŒã®ã«ãŒãã決å®ããããã«èšèšãããGetRootããŒãµãŒã¡ãœãããåŒã³åºãããŸãã 次ã«ãèŠã€ãã£ããã¹ãŠã®ã«ãŒããé åã«çµåãããŸãã
GetRootã¡ãœããïŒ
å
éšExpressionTreeNode GetRootïŒçšèª[]ã°ã«ãŒããMathExpression MathExpressionïŒ
/// <summary> </summary> /// <param name="Group"> </param> /// <param name="MathExpression"> </param> /// <returns> .</returns> internal ExpressionTreeNode GetRoot([NotNull] Term[] Group, [NotNull] MathExpression MathExpression) { Contract.Requires(Group != null); Contract.Requires(MathExpression != null); Contract.Ensures(Contract.Result<ExpressionTreeNode>() != null); // ExpressionTreeNode Last = null; for(var i = 0; i < Group.Length; i++) // { var node = Group[i].GetSubTree(this, MathExpression); // // ... if(Group[i] is NumberTerm) // ... , { //... if(i + 2 < Group.Length && NumberTerm.TryAddFractionPart(ref node, Group[i + 1], DecimalSeparator, Group[i + 2])) i += 2; //... . } else if(Group[i] is BlockTerm) //... ( ) node = new ComputedBracketNode( // - new Bracket( // : (((BlockTerm)Group[i]).OpenBracket), // ((BlockTerm)Group[i]).CloseBracket), // node); // // Combine(Last, Last = node); // if(Last.IsRoot && Last is VariantOperatorNode && Last.Left is VariableValueNode) Last = new FunctionArgumentNameNode(((VariableValueNode)Last.Left).Name); OnNewNodeAdded(ref Last); } // , if(Last == null) throw new FormatException(); return Last.Root; // }
ããã§ã¯ãåŒã®çšèªã®å ¥åé åãé 次ã¹ãã£ã³ãããŸããåŒã®é£ç¶ããåé ããããã®ããªãŒã®ã«ãŒããæœåºããŸãïŒããã§ååž°ãçºçããŸãïŒã次ã«ã以äžã確èªããå¿ èŠããããŸãã-
çŸåšã®é ãæŽæ°ã§ãé åã®æåŸããå°ãªããšã3çªç®ã®å ŽåãçŸåšã®ããŒãã«å°æ°éšåãè¿œå ããããšããŸãã
public static bool TryAddFractionPartïŒref ExpressionTreeNodeããŒããTerm SeparatorTermãchar DecimalSeparatorãTerm FrationPartTermïŒ
/// <summary> </summary> /// <param name="node"> </param> /// <param name="SeparatorTerm"> </param> /// <param name="DecimalSeparator"> </param> /// <param name="FrationPartTerm"> </param> /// <returns>, . , </returns> public static bool TryAddFractionPart(ref ExpressionTreeNode node, Term SeparatorTerm, char DecimalSeparator, Term FrationPartTerm) { var value = node as ConstValueNode; if(value == null) throw new ArgumentException(" "); var separator = SeparatorTerm as CharTerm; if(separator == null || separator.Value != DecimalSeparator) return false; var fraction = FrationPartTerm as NumberTerm; if(fraction == null) return false; var v_value = fraction.Value; if(v_value == 0) return true; node = new ConstValueNode(value.Value + v_value / Math.Pow(10, Math.Truncate(Math.Log10(v_value)) + 1)); return true; }
ãã®ã¡ãœããã¯ã10é²æ°ã®æŽæ°éšåãšå°æ°éšåã®åºåãæåãããã³çŸåšã®çšèªã«ç¶ã2ã€ã®çšèªã瀺ããŸãã2çªç®ã®çšèªãã·ã³ããªãã¯ã§åºåãæåãå«ã¿ã3çªç®ãæ°å€ã§ããå ŽåãããŒãã¯æ°ããå®æ°å€ããŒãã«çœ®ãæããããŸã-2
çªç®ã®ãã§ãã¯ã¯ãçŸåšã®çšèªããããã¯ã§ããå Žåããããã¯ãããã¯ããŒãã圢æãããŸã
ãã§ãã¯ãå®äºãããšãåã®ãµã€ã¯ã«ã§äœæãããããŒããšçŸåšã®ãµã€ã¯ã«ãçµã¿åãããã¡ãœãããå®è¡ãããŸãã
public virtual void CombineïŒExpressionTreeNode LastãExpressionTreeNode NodeïŒ
/// <summary> </summary> /// <param name="Last"> ( )</param> /// <param name="Node"> , </param> // ReSharper disable once CyclomaticComplexity public virtual void Combine([CanBeNull] ExpressionTreeNode Last, [NotNull] ExpressionTreeNode Node) { Contract.Requires(Node != null); if(Last == null) return; // , if(Node is CharNode) // - , { Last.LastRightChild = Node; // return; } var operator_node = Node as OperatorNode; // - if(operator_node != null) // ... { // : // // var parent_operator = Last as OperatorNode ?? Last.Parent as OperatorNode; if(parent_operator != null) // - ( )... { // - // op <- // | // op // / \ // null ? if(parent_operator.Left == null && parent_operator.Parent is OperatorNode) parent_operator = (OperatorNode)parent_operator.Parent; if(parent_operator.Left == null) // ... operator_node.Left = parent_operator; // else if(parent_operator.Right == null) // parent_operator.Right = Node; // else // { var priority = operator_node.Priority; // // , if(priority <= parent_operator.Priority) { // parent_operator = (OperatorNode)parent_operator.Parents // .TakeWhile(n => n is OperatorNode && priority <= ((OperatorNode)n).Priority) // .LastOrDefault() ?? parent_operator; // , // if(parent_operator.IsRoot) // - // , if(priority <= parent_operator.Priority) // operator_node.Left = parent_operator; else // { var parent = parent_operator.Parent; // parent.Right = Node; // operator_node.Left = parent_operator;// } } else // { // parent_operator = (OperatorNode)parent_operator.RightNodes // .TakeWhile(n => n is OperatorNode && n.Left != null && ((OperatorNode)n).Priority < priority) // .LastOrDefault() ?? parent_operator; // , // var right = parent_operator.Right; // parent_operator.Right = Node; // operator_node.Left = right; // } } } else // { var parent = Last.Parent; var is_left = Last.IsLeftSubtree; var is_right = Last.IsRightSubtree; operator_node.Left = Last; // if(is_left) parent.Left = operator_node; else if(is_right) parent.Right = operator_node; } return; // } // if(Last is OperatorNode) // { Last.Right = Node; // return; // } // // , - if(Last is ConstValueNode || (Last is ComputedBracketNode && Node is ComputedBracketNode)) { // var parent = Last.Parent; if(parent != null) // // parent.Right = new MultiplicationOperatorNode(Last, Node); else // // - , new MultiplicationOperatorNode(Last, Node); return; // . } Last.Right = Node; }
ããã¯äžå¿çãªæ¹æ³ã®1ã€ã§ããäœæãããæ°åŒããªãŒã®ããžãã¯ã«åŸã£ãŠãæŒç®åããŒãïŒãããã®åªå é äœïŒãèæ ®ããŠãæ¢åã®ããŒãã«æ°ããããŒããã¢ã¿ããããŸãããã¡ãããã¡ãœããã¯ã³ãŒãã®ãµã€ãºã®ããã«ãªãã¡ã¯ã¿ãªã³ã°ãå¿ èŠãšããŸãã圌ã®äœåã®è«çã¯ãã³ãŒãã®ã³ã¡ã³ãã«åæ ãããŠããŸãã
2ã€ã®ããŒãã®çµã¿åãããå®äºãããšãæåŸã®ãã§ãã¯ãå®è¡ãããŸããåŠçãããããŒããããªãŒã®ã«ãŒãã§ãããããŒããéžæè¢ã®ããŒãã§ããããã®å ŽåããŒãå€æ°<Variable>ïŒ<option_2>ãå·ŠãµãããªãŒã«ããå ŽåãåŒæ°åŒæ°<argument_nameã®ããŒããšèŠãªãããå¿ èŠããããŸã>ïŒ<argument_value>ããã®å ŽåãåŒæ°ã®ååã¯å€æ°åã«ãªããŸãã
å埩ãå®äºãããšãããŒãµãŒãªããžã§ã¯ãã§NewNodeAddedã€ãã³ããçæãããäœæãããããŒãã¯ãŠãŒã¶ãŒã«ããå€éšåŠçã®ããã«æž¡ãããŸãããã®å ŽåãããŒãã¯åç §ã«ãã£ãŠæž¡ããããããäœæãããããªãŒãå®å šã«ãªãŒããŒã©ã€ãããå¯èœæ§ããããŸãã
ããŒãµãŒã«ãã£ãŠçšèªã®ã°ã«ãŒãã«å¯ŸããŠãµãããªãŒãäœæããããããã¯çšèªã®GetSubTreeã¡ãœããã§ããã®ãããªãµãããªãŒã®ãã¹ãŠã®ã«ãŒããé åã«çµåãããåŸãã¡ãœããã¯ãã§ãã¯ããŸãã
- é åã«èŠçŽ ã1ã€ããå«ãŸããŠããªãå ŽåãçµæãšããŠè¿ãããŸãïŒããã¯ç°¡åãªã±ãŒã¹ã§ãïŒ
- å€ãã®ã«ãŒããããå Žåããããã®ããããã¯FunctionArgumentNodeé¢æ°ã®åŒæ°ã®ããŒãïŒå³åŽã®ãµãããªãŒå ïŒã«ããã¯ããã次ã®åŒæ°ã¯å·ŠåŽã®ãµãããªãŒã«ããã¿ã€ããŸãã
åŒããªãŒã®æ§é
ãããã£ãŠãçæãããããªãŒã¯æ¬¡ã®ã«ãŒã«ãæºãããŸãã
- (, ) ( )
- . .
- , . ;
- â -, -.
- . ( ).
é¢æ°ãšæ©èœèªäœã¯ãå¥ã ã®ãªããžã§ã¯ãã«å²ãåœãŠãããŸãã
ããªãŒãæ§ç¯ãããŸããæ§ç¯ããã»ã¹äžã«ãå€æ°ãšé¢æ°ã®ããŒããäœæãããŸããããã®ãããªåããŒãã¯ã察å¿ããã¿ã€ãã®ããŒãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãžã®çŽæ¥åŒã³åºãã«ãã£ãŠã察å¿ããçšèªã«ãã£ãŠäœæãããŸããã
ã¯ã©ã¹StringTermïŒçšèª{...}
/// <summary> </summary> class StringTerm : Term { /// <summary> </summary> [NotNull] public string Name => f_Value; /// <summary> </summary> /// <param name="Name"> </param> public StringTerm([NotNull] string Name) : base(Name) { Contract.Requires(!string.IsNullOrEmpty(Name)); } /// <summary> , -</summary> /// <param name="Parser"></param> /// <param name="Expression"> </param> /// <returns> , Expression.Variable[Name]</returns> public override ExpressionTreeNode GetSubTree(ExpressionParser Parser, MathExpression Expression) => new VariableValueNode(Expression.Variable[Name]); } /// <summary> </summary> sealed class FunctionalTerm : FunctionTerm { /// <summary> </summary> [NotNull] public BlockTerm Parameters { get; set; } /// <summary> </summary> /// <param name="Header"> </param> /// <param name="Body"> </param> public FunctionalTerm([NotNull] FunctionTerm Header, [NotNull] BlockTerm Body) : base(Header.Name, Body) { Contract.Requires(Header != null); Contract.Requires(Body != null); Parameters = Header.Block; } /// <summary> </summary> /// <param name="Parser"></param> /// <param name="Expression"> </param> /// <returns> </returns> public override ExpressionTreeNode GetSubTree(ExpressionParser Parser, MathExpression Expression) => new FunctionalNode(this, Parser, Expression); public override string ToString() => $"{Name}{Parameters}{Block}"; }
åæã«ãããŒããäœæãããšããåŒã«ã¯ãç®çã®å€æ°ãªããžã§ã¯ã/é¢æ°ãååã§æœåºããããã®å€æ°/é¢æ°ã®ã³ã¬ã¯ã·ã§ã³ãå¿ èŠã§ãã
å
éšFunctionNodeïŒFunctionTermçšèªãExpressionParserããŒãµãŒãMathExpressionåŒïŒ
/// <summary> </summary> /// <param name="Term"> </param> /// <param name="Parser"> </param> /// <param name="Expression"> </param> internal FunctionNode(FunctionTerm Term, ExpressionParser Parser, MathExpression Expression) : this(Term.Name) { var arg = Term.Block.GetSubTree(Parser, Expression); if(!(arg is FunctionArgumentNode)) if(arg is FunctionArgumentNameNode) arg = new FunctionArgumentNode((FunctionArgumentNameNode)arg); else if(arg is VariableValueNode) arg = new FunctionArgumentNode(null, arg); else if(arg is VariantOperatorNode && arg.Left is VariableValueNode) arg = new FunctionArgumentNode(((VariableValueNode)arg.Left).Name, arg.Right); else arg = new FunctionArgumentNode(null, arg); Right = arg; // - Function = Expression.Functions[Name, ArgumentsNames]; }
æ°åŒãªããžã§ã¯ãã§ããªãŒãäœæãããåŸãå€æ°ãšé¢æ°ã®ã³ã¬ã¯ã·ã§ã³ã«ã¯äœ¿çšããããªããžã§ã¯ãã®ãªã¹ããå«ãŸããŸãããããããããã®æå³ã¯ç©ºã§ããäžéšã®å€æ°ã¯ãããŒãµãŒã«æ¢ç¥ã®å®æ°ãšããŠåé¡ããå¿ èŠããããŸãïŒé©åãªã³ã¬ã¯ã·ã§ã³ã«è»¢éããŸããé¢æ°ãªããžã§ã¯ãã¯ãããããå®è£ ããããªã²ãŒãã«ãã£ãŠå®çŸ©ããå¿ èŠããããŸãã
ããªãŒã®åæå
æ°åŒã®ãçã®ãããªãŒãäœæããåŸãå€æ°ãšé¢æ°ã®å€ãå ¥åããå¿ èŠããããŸããããŒãµãŒã®Parseã¡ãœããã¯ãProcessVariablesãšProcessFunctionsã®2ã€ã®ã¡ãœãããé çªã«åŒã³åºããŠãäœæããããçã®ãããªãŒãæž¡ããŸãã
å€æ°åŠçæ¹æ³ïŒ
å
éšvoid ProcessVariablesïŒMathExpressionåŒïŒ
/// <summary> </summary> /// <param name="Expression"> </param> internal void ProcessVariables([NotNull] MathExpression Expression) { Contract.Requires(Expression != null); var tree_vars = Expression.Tree.Root.GetVariables().ToArray(); Expression.Variable .Where(v => !tree_vars.Contains(v)) .ToArray() .Foreach(v => Expression.Variable.Remove(v)); foreach(var variable in Expression.Variable.ToArray()) { if(f_Constans.ContainsKey(variable.Name)) { Expression.Variable.MoveToConstCollection(variable); variable.Value = f_Constans[variable.Name]; } OnVariableProcessing(variable); } }
ãã®ã¿ã¹ã¯ã¯ãããªãŒãäžåšãããã¹ãŠã®å€æ°ããŒããèŠã€ããŠããããã§äœ¿çšãããŠããå€æ°ãªããžã§ã¯ããæœåºããããšã§ãããã®åŸãããªãŒã§äœ¿çšãããŠããªããã¹ãŠã®ãã®ãæ°åŒã®å€æ°ã®ã³ã¬ã¯ã·ã§ã³ããåé€ããå¿ èŠããããŸãã
ãã®åŸãããªãŒå ã®åå€æ°ã«ã€ããŠããã®ååãæ¢ç¥ã®ããŒãµãŒå®æ°ã®ã³ã¬ã¯ã·ã§ã³ã«å«ãŸããŠãããã©ããããã§ãã¯ãããŸããããã§ããå ŽåãåŒã®å€æ°ã®ã³ã¬ã¯ã·ã§ã³ããåé€ãããåŒã®å®æ°ã®ã³ã¬ã¯ã·ã§ã³ã«å ¥åãããããŒãµãŒã«æ¢ç¥ã®å€ã§åæåãããå®æ°ã§ãããšãããã©ã°ãèšå®ãããŸãã
ãã®åŸãããŒãµãŒã§æ°ããå€æ°ãæ€åºããã€ãã³ããçºçããŸãããã®ã€ãã³ããåŠçãããšããããŒãµãŒãŠãŒã¶ãŒã¯ãã®å€æ°ã®å€ããªãŒããŒã©ã€ãããããå€æ°ãªããžã§ã¯ãèªäœãå€æŽã§ããŸãã
2çªç®ã®ProcessFunctionsã¡ãœããã¯ãåŒã«æ¢ç¥ã®é¢æ°ã§ããªã²ãŒããåããŸãã
å
éšvoid ProcessFunctionsïŒMathExpressionåŒïŒ
/// <summary> </summary> /// <param name="Expression"> </param> [SuppressMessage("ReSharper", "CyclomaticComplexity")] internal void ProcessFunctions([NotNull] MathExpression Expression) { Contract.Requires(Expression != null); foreach(var function in Expression.Functions) switch(function.Name) { case "Sin": case "SIN": case "sin": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Sin); break; case "COS": case "Cos": case "cos": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Cos); break; case "TAN": case "Tan": case "tan": case "tn": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Tan); break; case "ATAN": case "ATan": case "Atan": case "atan": case "atn": case "Atn": if(function.Arguments.Length == 1) function.Delegate = new Func<double, double>(Math.Atan); else if(function.Arguments.Length == 2) function.Delegate = new Func<double, double, double>(Math.Atan2); else goto default; break; case "Atan2": case "atan2": if(function.Arguments.Length != 2) goto default; function.Delegate = new Func<double, double, double>(Math.Atan2); break; case "CTG": case "Ctg": case "ctg": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(x => 1 / Math.Tan(x)); break; case "Sign": case "sign": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(x => Math.Sign(x)); break; case "Abs": case "abs": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Abs); break; case "Exp": case "EXP": case "exp": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Exp); break; case "Sqrt": case "SQRT": case "â": case "sqrt": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Sqrt); break; case "log10": case "Log10": case "LOG10": case "lg": case "Lg": case "LG": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Log10); break; case "loge": case "Loge": case "LOGe": case "ln": case "Ln": case "LN": if(function.Arguments.Length != 1) goto default; function.Delegate = new Func<double, double>(Math.Log); break; case "log": case "Log": case "LOG": if(function.Arguments.Length != 2) goto default; function.Delegate = new Func<double, double, double>(Math.Log); break; default: var f = OnFunctionFind(function.Name, function.Arguments); if(f == null) throw new NotSupportedException($" {function.Name} "); function.Delegate = f; break; } }
é¢æ°åãcaseæŒç®åã®ããªã¢ã³ãã«å«ãŸããŠããå Žåãå¿ èŠãªé¢æ°ãåŒæ°ã®æ°ãšäžèŽãããšãããªã²ãŒããããã«å²ãåœãŠããããã®å€ãèšç®ãããŸããé¢æ°ãå®çŸ©ãããŠããªãå Žåãããªã²ãŒãã¯æªç¥ã®é¢æ°æ€åºã€ãã³ãã®çæã®çµæãšããŠå®çŸ©ãããŸãããã®å ŽåããŠãŒã¶ãŒã¯ãåŒæ°ã®ååãšæ°ïŒããã³ååïŒã«ãã£ãŠããã®ã€ãã³ããžã®å¿çã§å¿ èŠãªããªã²ãŒãã決å®ã§ããŸãã
ããã§ãæ°åŒã®çæãå®äºããŸããã
䜿çšãã
ç§ãã¡ã®ä»äºã¯ãé¢æ°A * cosïŒ2 * xïŒ/ pi + GïŒx / 2ïŒãAãš+ 1ã§é€ç®ããç©åãèšç®ããããšã§ãããšä»®å®ããŸããããšãã°ãAã5ã®å Žåã0.05ã®å¢åã§ç©åããšãå¿ èŠããããŸãã
var parser = new ExpressionParser(); parser .FindFunction += (s, e) => { if(e.SignatureEqual(name: "G", ArgumentsCount: 1)) e.Function = new Func<double, double>(x => 2 * Math.Cos(x)); }; var expr = parser.Parse(@"Int[x=-10..10;dx=0.05]{A*cos(2x) + G(x/2)}/A + 1"); expr.Variable["A"] = 5; var y = expr.Compute(); //y = 0.30928806858920344 var f = expr.Compile(); var y2 = f(); //y = 0.30928806858920344
ãããã«
èšäºã®çµæã®ããªã¥ãŒã ãèãããšãããã«ããªãªãã§ã¯ãªãã»ãã³ãã³ãå ¥ããŸãããäžèšã®çµæã次ã®ããšãå¯èœã«ãªããŸããã
- åé¡ã解決ããæ¹æ³ã®äžè¬çãªã¢ã€ãã¢ãå ¥æããŠãã ããã
- æ°åŒã®ããŒãµãŒãæ°åŒèªäœãããã³ãã®ããªãŒã®ãªããžã§ã¯ãã¢ãã«ã圢æããã«ã¯ã
- æ°åŒãè«çã³ã³ããŒãã³ãã«è§£æããããã®å¹æçãªæ¹æ³ãäœæããŸãã
- æ¬åŒ§ã®äœ¿çšã®ç¹æ®æ§ãæŒç®åã®åªå é äœãããã³ç¹å¥ãªæ§æïŒé¢æ°ïŒãèæ ®ããŠãæ°åŒã®ããªãŒãæ§ç¯ããããã®å¹æçãªæ¹æ³ãäœæããŸãã
- ã€ãã³ãã·ã¹ãã ã«åºã¥ããŠãããŒãµãŒãå ¥åããŒã¿ãåŠçããããŸããŸãªæ®µéãå¶åŸ¡ããŸãã
- æ©èœãæ¡åŒµããæ©èœãè¿œå ããŸãã
ãã®èšäºã§ã¯èª¬æã§ããªãã£ããã®ïŒ
- å€æ°ã®è«çïŒãããã®æºåãšãã®åŸã®çœ®æã®ã¿ã€ããšæ¹æ³ïŒ;
- æ°åŒã®äœæ¥ã«é¢äžããå€æ°ãå®æ°ãé¢æ°ã®ã³ã¬ã¯ã·ã§ã³ã®æ§é ã
- ããªãŒãèµ°æ»ããŠæ°åŒã®å€ãèšç®ããæ¹æ³ã
- mat.expressionã®ããªãŒãããªã²ãŒãã«ã³ã³ãã€ã«ããããã®ã¡ãœããã
ããŒãµãŒèªäœã®å®è£ ã§ãããŸã§ã«å€±æãããã®ïŒ
- æ°åŒã®ããªãŒãæé©åããã¡ãœãããå®è£ ããŸãã
- å€ãã®å ŽæããæŸèæãåãå€ããŸãã
- å ¥åããŒã¿ããããã®åœ¢åŒã«æºæ ããŠãããã©ããã®ãã§ãã¯ãè¿œå ããŸãã
- å®éã«ããã®åœ¢åŒã®å¢çãæŠèª¬ããŠãã ããã
- åäœãã¹ãã§ã³ãŒãã«ãã¬ããžãå¢ãããŸãã
- åæã®æ®µéãšèšç®ã®æ®µéã®äž¡æ¹ã®ããã©ãŒãã³ã¹ã®æ¯èŒç 究ãå®æœããŸãã
äžè¬ã«ããã®ã³ãŒãã®äœæ¥ã«ã¯æ®å¿µãªããèæ¯æåããããæ°å¹Žç¶ããŠããŸããããã®æ®µéã§å²ãåœãŠãããã¿ã¹ã¯ã¯æ¢ã«è§£æ±ºããŠããŸããçŸåšã®åœ¢ã§ã¯åœŒãçç£ã«å ¥ããããšã¯äžå¯èœã§ãã
å®å šãªãœãŒã¹ã³ãŒãã¯ããã§èŠã€ããããšãã§ããŸãã