
䜿çšæžã¿ã®ããã°ã©ã ãšã©ã€ãã©ãª
- GOLD Parsing System-ææ³ãèšè¿°ããããŸããŸãªèšèªïŒCãCïŒãJavaãJavaScriptãObjective-CãPerlãPythonãRubyãªã©ïŒã®ã¬ã¯ãµãŒãšããŒãµãŒã®ã³ãŒããçæããIDEã LALR解æã«åºã¥ããŠããŸãã
- Visual Studio 2010
- GOLD.Engine-çæãããããŒãã«ãšå¯Ÿè©±ããããã«æ¥ç¶ããã.NETã®ã¢ã»ã³ããªã
- NUnit-.NETçšã®ãªãŒãã³ãœãŒã¹ã®åäœãã¹ãç°å¢ã
- ILSpy-.NETçšã®ãªãŒãã³ãœãŒã¹éã¢ã»ã³ãã©ãŒ ã
ããã»ã¹å šäœãå£ãã段éïŒ
- åŒããªãŒã®æ§ç¯
- åæå°é¢æ°ã®èšç®
- åŒã®ç°¡ç¥å
- åççãªåæ°åŠç
- åŒã®ã³ã³ãã€ã«
åŒããªãŒã®æ§ç¯
GANTããŒãµãŒãžã§ãã¬ãŒã¿ãŒãéžæããŸãããANTLRã®çµéšããããæ°ãããã®ã欲ããã£ãããã§ãã ãŸãããã®å©ç¹ã¯ãä»ãšæ¯èŒããŠããã®è¡šã§èŠãããšãã§ããŸã ã ã芧ã®ãšãããANTLRãšæ¯èŒãããšãGOLDã¯LLã§ã¯ãªãLALRã¢ã«ãŽãªãºã ã«åºã¥ããŠããŸãã ããã¯ãçè«çã«ã¯ãçæãããããŒãµãŒã¯ããé«éã§åŒ·åã§ãããäžæ¹ã§ãããã°ã§ããªãããšãæå³ããŸãïŒGOLDã§ã¯ããã¡ã€ã«ã¯ãã€ããªåœ¢åŒã§ããŠã³ããŒããããŸãïŒãå¯èœã§ããã°ãå®å šã«äžæçã§äžäŸ¿ã§ãã ãã1ã€ã®å€§ããªéãã¯ãææ³åœ¢åŒïŒ EBNFã§ã¯ãªãBNFã§ãã ããã¯ããã®åœ¢åŒã§æžãããææ³ã¯ãå±±æ¬åŒ§ãå®çŸ©ã®èšå·ãæ¡ä»¶ä»ãã®åºçŸãšç¹°ãè¿ãã®æ¬ åŠã®ããã«ãããã«å€§ãããµã€ãºãæã€ããšãæå³ããŸã ïŒ wikiã«ãããŸã ããŸããäŸãã°ãEBNFã®ãããªã«ãŒã«
ExpressionList = Expression { ',' Expression }
次ã®åœ¢åŒã§æžãæããããŸãã
<ExpressionList> ::= <ExpressionList> ',' <Expression> | <Expression>
ãããã£ãŠãæ°åŒã®æçµçãªææ³ã¯æ¬¡ã®åœ¢åŒã«ãªããŸãã
æ°åŒã®ææ³
"Name" = 'Mathematics expressions' "Author" = 'Ivan Kochurkin' "Version" = '1.0' "About" = '' "Case Sensitive" = False "Start Symbol" = <Statements> Id = {Letter}{AlphaNumeric}* Number1 = {Digit}+('.'{Digit}*('('{Digit}*')')?)? Number2 = '.'{Digit}*('('{Digit}*')')? AddLiteral = '+' | '-' MultLiteral = '*' | '/' <Statements> ::= <Statements> <Devider> <Statement> | <Statements> <Devider> | <Statement> <Devider> ::= ';' | '.' <Statement> ::= <Expression> '=' <Expression> | <Expression> <Expression> ::= <FuncDef> | <Addition> <FuncDef> ::= Id '(' <ExpressionList> ')' | Id '' '(' <ExpressionList> ')' | Id '(' <ExpressionList> ')' '' <ExpressionList> ::= <ExpressionList> ',' <Expression> | <Expression> <Addition> ::= <Addition> AddLiteral <Multiplication> | <Addition> AddLiteral <FuncDef> | <FuncDef> AddLiteral <Multiplication> | <FuncDef> AddLiteral <FuncDef> | <Multiplication> <Multiplication> ::= <Multiplication> MultLiteral <Exponentiation> | <Multiplication> MultLiteral <FuncDef> | <FuncDef> MultLiteral <Exponentiation> | <FuncDef> MultLiteral <FuncDef> | <Exponentiation> <Exponentiation> ::= <Exponentiation> '^' <Negation> | <Exponentiation> '^' <FuncDef> | <FuncDef> '^' <Negation> | <FuncDef> '^' <FuncDef> | <Negation> <Negation> ::= AddLiteral <Value> | AddLiteral <FuncDef> | <Value> <Value> ::= Id | Number1 | Number2 | '(' <Expression> ')' | '|' <Expression> '|' | '(' <Expression> ')' '' | '|' <Expression> '|' '' | Id ''
ããŒã¯ã³ãé€ããŠãææ³ã§ã¯ãã¹ãŠãæãããªããã§ãïŒ Number1 = {Digit} +ïŒ 'ã' {Digit} *ïŒ 'ïŒ' {Digit} * 'ïŒ'ïŒïŒïŒïŒ ãã®èšèšã«ããã次ã®åœ¢åŒã®è¡ã解æã§ããŸãã0.1234ïŒ56ïŒãããã¯ãåççãªå°æ°éšãæå³ããïŒ61111/495000 ãã®ãããªæååãåæ°ã«å€æããæ¹æ³ã«ã€ããŠã¯ãåŸã§èª¬æããŸãã
ãããã£ãŠãã³ã³ãã€ã«æžã¿ã®ææ³ããŒãã«ïŒã³ã³ãã€ã«æžã¿ææ³ããŒãã«ãã¡ã€ã«ïŒãçæãããããŒãµãŒã¯ã©ã¹ãã¬ãŒã ã¯ãŒã¯ãäœæãããåŸãé©åãªASTããªãŒãæ§ç¯ããããã«åŸè ãå€æŽããå¿ èŠããããŸãã ãã®å Žåã®ããŒãµãŒã¯ã©ã¹ãã¬ãŒã ã¯ãŒã¯ã¯ããã¹ãŠã®ææ³ã«ãŒã«ã®ã«ãŒããããŒã¯ã³ã®äžæ£ãªã·ãŒã±ã³ã¹ããã®ä»ã®ãšã©ãŒã®å Žåã®äŸå€åŠçãå«ã.csãã¡ã€ã«ã§ãïŒã¡ãªã¿ã«ãGOLDã«ã¯ãã®ãããªãã¬ãŒã ã¯ãŒã¯ã®ç°ãªããžã§ãã¬ãŒã¿ãŒããããCook .NETãéžæããŸããïŒ ãããã£ãŠããã®å Žåããé©åãªããšã¯ã次ã®ã¿ã€ããæã€ããšãã§ããããŒãã§æ§æãããããªãŒãæå³ããŸãã
- èšç®æžã¿ -ã³ã³ãã€ã©ãŒãåãå ¥ãå¯èœãªäºé圢åŒã§èšç®ãããå®æ°ãè¡šãããŒããããšãã°ãã0.714285714285714ããã0.12222222222222222ãã ããããåãã§ãã£ãŠãããã®ãããªå®æ°ããšã«æ°ãããªããžã§ã¯ããäœæãããŸãã
- å€ -èšç®ãããå®æ°ãæçæ°ã®åœ¢åŒã§è¡šãããŒããã€ãŸã 1ã¯ã1/1ããã0.1ïŒ2ïŒãã¯ã11/90ããã0.1234ãã¯ã617/5000ããšããŠè¡šãããŸãã ããããåãã§ãã£ãŠãããã®ãããªå®æ°ããšã«æ°ãããªããžã§ã¯ããäœæãããŸãã
- å®æ° -æªå®çŸ©ã®å®æ°ãè¡šãããŒããããšãã°ãaãããbããªã©ã2ã€ã®å®æ°ãåŒã§èŠã€ãã£ãå Žåããããã¯1ã€ã®ããŒããæããŸãã
- å€æ° - å€æ°ãè¡šãããŒããããšãã°ãxãããyããªã©ãç¹å®ã®å€æ°ãåŒã§è€æ°ååºçŸããå Žåããã®å€æ°ãšæªå®çŸ©ã®å®æ°ã«å¯ŸããŠ1ã€ã®ãªããžã§ã¯ãã®ã¿ãäœæãããŸãã å®æ°ãšå€æ°ã®åºå¥ã¯ãåæå°é¢æ°ã®å°åºã®æ®µéã§ã®ã¿éèŠã§ãããä»ã®å Žåããã®ç¥èã¯å¿ èŠãªãããšãç解ããããšãéèŠã§ãã
- é¢æ° - é¢æ°ãè¡šãããŒããããšãã°ãã+ãããsinããã^ããªã©ã åãæã€ããšãã§ããå¯äžã®ããŒãã
å³ã«ã¯ããã¹ãŠã®ã¿ã€ãã®ããŒããæ確ã«ç€ºãããŠããŸãã

ææ³ãããçµæã®ããªãŒã®ããŒãã«ã¯åïŒå€ãå€æ°ãªã©ïŒããªãããæšæºé¢æ°ïŒcosãå ç®ãã¹ãä¹ãªã©ïŒã®å Žåã¯1ã2åã®åãããããšãããããŸãã ä»ã®ãã¹ãŠã®é¢æ°ã«ã¯ããã«åŒæ°ããããŸãããèæ ®ãããŸããã§ããã
ãããã£ãŠããã¹ãŠã®ããŒãïŒãŸãã¯æ©èœãæã€ããŒãïŒã«ã¯ã0ã2åã®åãå«ãŸããŸãã ããã¯çè«çãªèŠ³ç¹ããåœãŠã¯ãŸããŸãã ããããå®éã«ã¯ãã+ãããã³ã*ãé¢æ°ã®åã®æ°ãç¡å¶éã«ããåŸã§æ€èšããåçŽåã®ã¿ã¹ã¯ã容æã«ããå¿ èŠããããŸããã ã¡ãªã¿ã«ãã-ããã/ããªã©ã®ãã€ããªæŒç®ãåãçç±ã§ç Žæ£ããå¿ èŠããããŸããïŒå³åŽã®åŠå®ã«ããå ç®ãšå³åŽã®å転ã«ããä¹ç®ã«çœ®ãæããããŸããïŒã
ãã®ããã解æ段éã§ãåã«ãŒã«ã®ãã¹ãŠã®ããŒããèœã¡ããã Nodesãšãããããã¡ãŒããååŸãããŸãã ãããã£ãŠãããã»ã¹å šäœã®æåŸã«ãå³åŽãšå·ŠåŽã®éšåãæã€1ã€ä»¥äžã®é¢æ°ããã®ãããã¡ãŒã«æ®ããŸãã ãŸããæ§æ解æã®éçšã§ãå ç®é¢æ°ãšä¹ç®é¢æ°ãå€åœèªã§ããã«äœæãããããã«ãé¢æ°ã®çŸåšã®åŒæ°ã®æ°ãšçŸåšã®é¢æ°ã®åãããããæ ŒçŽããè¿œå ã®ãããã¡ãŒArgsCountãšArgsFuncTypesã䜿çšãããŸããã ãããã£ãŠãããšãã°ãä¹ç®é¢æ°ã®å Žåã次ã®ã³ãŒãã䜿çšãããŸãã
æåã®ä¹æ°ã®åŠçïŒ
// <Multiplication> ::= <Exponentiation> if (MultiplicationMultiChilds) PushFunc(KnownMathFunctionType.Mult);
içªç®ã®ä¹æ°ã®åŠçïŒ
// <Multiplication> ::= <Multiplication> MultLiteral <Exponentiation> // <Multiplication> ::= <Multiplication> MultLiteral <FuncDef> if (KnownMathFunction.BinaryNamesFuncs[r[1].Data.ToString()] == KnownMathFunctionType.Div) Nodes.Push(new FuncNode(KnownMathFunctionType.Exp, new MathFuncNode[] { Nodes.Pop(), new ValueNode(-1) })); ArgsCount[ArgsCount.Count - 1]++;
æåŸã®ä¹æ°ã®åŠçïŒ
// <Addition> ::= <Multiplication> if (MultiplicationMultiChilds) PushOrRemoveFunc(KnownMathFunctionType.Mult); if (AdditionMultiChilds) PushFunc(KnownMathFunctionType.Add);
ãã®ã³ãŒãã¯ãããšãã°ãä¹ç®ããªãå Žåã PushOrRemoveFuncã䜿çšããŠèŠçŽ ããŒãã®æåŸã®ä¹ç®é¢æ°ãåé€ããå¿ èŠãããããšã瀺ããŠããŸãã è¿œå ããã«ã¯ãåæ§ã®ã¢ã¯ã·ã§ã³ãå®è¡ããå¿ èŠããããŸãã
åäžã®åŒæ°ã®é¢æ°ããã€ããªé¢æ°ãå®æ°ãå€æ°ãå€ã®åŠçã¯ç°¡åã§ããã MathExprParser.csã§ããããã¹ãŠã確èªã§ããŸãã
åæå°é¢æ°ã®èšç®
ãã®æ®µéã§ãé¢æ°ããã®å°é¢æ°ã«å€æããå¿ èŠããããŸãã
æåã®æ®µéãããããããã«ãäœæãããåŒããªãŒã«ã¯4ã€ã®ã¿ã€ãã®ããŒããããããŸããïŒ5çªç®ã®ããŒãã¯åŸã§è¡šç€ºãããŸãïŒã ãããã«ã€ããŠãå°é¢æ°ãå®çŸ©ããŸãã
- å€ '= 0
- å®æ° '= 0
- å€æ° '= 1
- é¢æ° '=èªå°äœ[é¢æ°]
説æããŠã¿ãŸãããïŒå°é¢æ°ã«ã€ããŠã¯ãäºåã«æºåããã衚圢åŒã®å€ãååŸããå¿ èŠãããããã®å€ã«ã¯å°é¢æ°ããããããç¹å®ã®å°é£ãçããŸãã ããã»ã¹ã¯æ¬è³ªçã«ååž°çã§ãã ãã®ãããªå®è£ ããã眮æã®å®å šãªãªã¹ãã¯ã以äžã®ãã¿ãã¬ã®äžã«ãããŸãã
ããªããã£ãã®ãªã¹ã
(f(x) ^ g(x))' = f(x) ^ g(x) * (f(x)' * g(x) / f(x) + g(x)' * ln(f(x)));"); neg(f(x))' = neg(f(x)');"); sin(f(x))' = cos(f(x)) * f(x)'; cos(f(x))' = -sin(f(x)) * f(x)'; tan(f(x))' = f(x)' / cos(f(x)) ^ 2; cot(f(x))' = -f(x)' / sin(f(x)) ^ 2; arcsin(f(x))' = f(x)' / sqrt(1 - f(x) ^ 2); arccos(f(x))' = -f(x)' / sqrt(1 - f(x) ^ 2); arctan(f(x))' = f(x)' / (1 + f(x) ^ 2); arccot(f(x))' = -f(x)' / (1 + f(x) ^ 2); sinh(f(x))' = f(x)' * cosh(x); cosh(f(x))' = f(x)' * sinh(x); arcsinh(f(x))' = f(x)' / sqrt(f(x) ^ 2 + 1); arcosh(f(x))' = f(x)' / sqrt(f(x) ^ 2 - 1); ln(f(x))' = f(x)' / f(x); log(f(x), g(x))' = g'(x)/(g(x)*ln(f(x))) - (f'(x)*ln(g(x)))/(f(x)*ln(f(x))^2);
ãã¹ãŠã®æŽŸçç©ãã³ãŒãå ã§ããŒãã«èšè¿°ãããŠããããã§ã¯ãªããåçã«å ¥åããã³è§£æããããšãã§ããŸãã
äžèšã®ããã«ããããã¯ããã€ãã®åŒæ°ãæã€é¢æ°ã§ããããããã®ãªã¹ãã«ã¯å ç®ãŸãã¯ä¹ç®ã¯ãããŸããã ãããŠããã®ãããªã«ãŒã«ã解æããã«ã¯ãå€ãã®ã³ãŒããæžãå¿ èŠããããŸãã åãçç±ã§ãæ©èœã®æ§æã¯ãããŸããã ïŒfïŒgïŒxïŒïŒïŒ '= fïŒgïŒxïŒïŒ' * gïŒxïŒ 'ã®ä»£ããã«ããã¹ãŠã®é¢æ°ã¯é¢æ°ã®æ§æãšããŠè¡šãããŸãã
ãŸããDerivativesã®é¢æ°ïŒã€ãŸããæªå®çŸ©ã®é¢æ°ïŒã®çœ®æãèŠã€ãããªãã£ãå Žåãããã¯åã«ã¹ãããŒã¯ã®ããé¢æ°ã«çœ®ãæããããŸãã fïŒxïŒã¯fïŒxïŒ 'ã«ãªããŸãã
åæå°é¢æ°ãæ£åžžã«ååŸãããåŸãçµæã®åŒã«ã¯ãa + 0ãa * 1ãa * a ^ -1ãªã©ãå€ãã®ãã¬ããŒãžãããããšããåé¡ãçºçããŸãããŸããçµæã®åŒã¯ããæé©ãªæ¹æ³ã§èšç®ã§ããŸãã ããšãã°ãåçŽãªåŒã§ãã£ãŠããèŠèŠããåŒã«ãªããŸãã
(x^2 + 2)' = 0 + 2 * 1 * x ^ 1
åçŽåã¯ããã®ãããªæ¬ ç¹ã«å¯ŸåŠããããã«äœ¿çšãããŸãã
åŒã®ç°¡ç¥å
ãã®æ®µéã§ã¯ãå°é¢æ°ãèšç®ãã段éãšã¯ç°ãªããåçŽãªèŠåãå¥ã®å Žæã«æžãçããŸããã§ãããå ç®ãšä¹ç®ã®é¢æ°ã¯ããã€ãã®åŒæ°ã®é¢æ°ã§ããããããã®ãããªèŠåãäœæããã®ã¯ããçšåºŠå°é£ã§ãå埩èšèªã®ã³ã³ããã¹ãã
ãããã¯ã®åé ã§ãå ç®ãšä¹ç®ãné é¢æ°ãšããŠè¡šãããçç±ã®ãããã¯ã«è§ŠããŸããã äžã®åçã«ç€ºãããŠããç¶æ³ãæ³åããŠãã ããã ããã§ãaãš-aãçç¥ãããŠããããšãããããŸãã ãããããã€ããªé¢æ°ã®å Žåã«ãããè¡ãæ¹æ³ã¯ïŒ ãããè¡ãã«ã¯ãããŒãa ã bãããã³cãå埩åŠçããŠã aããã³-aãåãããŒãã®åã§ããããšãåŸã§çºèŠããŸããããã¯ãããŒããšãšãã«ããŒããåæžã§ããããšãæå³ããŸãã ãã ããå³ã®å³ã«ç€ºãããã«ãããªãŒããœãŒãããããšã¯ãåçŽãªã¿ã¹ã¯ã§ã¯ãããŸããããã¹ãŠã®åãäžåºŠã«ãã¹ãŠã®ã¢ã¯ã·ã§ã³ãäžåºŠã«å®è¡ããæ¹ãã¯ããã«ç°¡åã ããã§ãã ãšããã§ããã®ãããªåæåã«ããã çµåæ§ãšå¯ææ§ã®æ°åŠçç¹æ§ãäœæã§ããŸãã
![]() | ![]() |
åçŽåããã»ã¹äžã«ã2ã€ã®ããŒããæ¯èŒãããšããåé¡ãçºçããŸãã2ã€ã®ããŒãã¯ã4ã€ã®ã¿ã€ãã®ããããã«ãªããŸãã ããã¯ãããšãã°ãsinïŒx + yïŒã-sinïŒx + yïŒãªã©ã®åŒãæžããããã«å¿ èŠã§ãã ããŒãããšã«ããŒãèªäœãšãã®ãã¹ãŠã®åå«ãæ¯èŒã§ããããšã¯æããã§ãã ããããåé¡ã¯ããã®æ¹æ³ã§ã¯ãããšãã°sinïŒx + yïŒã-sinïŒy + xïŒã®ããã«ãçšèªãå åãåé 眮ãããç¶æ³ã«å¯ŸåŠã§ããªãããšã§ãã ãã®åé¡ã解決ããããã«ãå¯ææ§ã®ç¹æ§ãæºããããçšèªãŸãã¯å åã®äºåçãªãœãŒãã䜿çšãããŸãïŒã€ãŸããå ç®ãšæžç®ïŒã ããŒãã¯ã次ã®å³ã«ç€ºãããã«æ¯èŒãããŸãã å€ã¯å®æ°ããå°ãããå®æ°ã¯å€æ°ããå°ããããªã©ã é¢æ°ã®å Žåãååã ãã§ãªãåŒæ°ã®æ°ãšåŒæ°èªäœãæ¯èŒããå¿ èŠãããããããã¹ãŠãå°ãè€éã«ãªããŸãã

ãããã£ãŠãäžèšã®ãã¹ãŠã®å€æãšåæã®åŸãå ã®åŒã¯éåžžã«åçŽåãããŸãã
åççãªåæ°åŠç
ç§ãèŠã€ããåççãªå®è£ ã§ã¯ãéåžžã®æåååãããšãã°0.666666ã¯ãç¹å®ã®ååãšåæ¯ãæã€åæ°åã«å€æãããŸããã§ããã äžå®ã®ç²ŸåºŠã§2/3ã§ã 次ã«ãå€ãã®ãªãã·ã§ã³ã䜿çšããŠå®è£ ãäœæããããšã«ããŸããã 以äžã®é¢æ°ã¯ãããšãã°ãç¹å®ã®æ°ãçŽç²ã«éåççã§ãããããããåšæãŸãã¯æéå°æ°éšãæã¡ãåççãªãã®ãããšãã°äžå®ã®ç²ŸåºŠã§sinïŒpiïŒãã0ã«å€æã§ãããã決å®ã§ããŸãã äžè¬çã«ã stackoverflow.comãžã®ç§ã®åçã®ãã®ä»ã®è©³çŽ°ãåç §ããŠãã ããã ã¡ãœããã®ç°¡åãªã°ã©ãã£ã«ã«ãªèª¬æãäžã®å³ã«ç€ºããã³ãŒããäžã®ãªã¹ãã«ç€ºããŸãã ããã«ãããããããæšæºçãªæ°åŠé¢æ°ãšdoubleåã®ç²ŸåºŠã¯ãæçæ°ãšå®æ°ã®éåžžã®èªèã«ã¯ååã§ã¯ãããŸããããçè«çã«ã¯ãã¹ãŠãæ©èœããããšã«æ³šæããŠãã ããã

å°æ°ãå°æ°ã«å€æ
/// <summary> /// Convert decimal to fraction /// </summary> /// <param name="value">decimal value to convert</param> /// <param name="result">result fraction if conversation is succsess</param> /// <param name="decimalPlaces">precision of considereation frac part of value</param> /// <param name="trimZeroes">trim zeroes on the right part of the value or not</param> /// <param name="minPeriodRepeat">minimum period repeating</param> /// <param name="digitsForReal">precision for determination value to real if period has not been founded</param> /// <returns></returns> public static bool FromDecimal(decimal value, out Rational<T> result, int decimalPlaces = 28, bool trimZeroes = false, decimal minPeriodRepeat = 2, int digitsForReal = 9) { var valueStr = value.ToString("0.0000000000000000000000000000", CultureInfo.InvariantCulture); var strs = valueStr.Split('.'); long intPart = long.Parse(strs[0]); string fracPartTrimEnd = strs[1].TrimEnd(new char[] { '0' }); string fracPart; if (trimZeroes) { fracPart = fracPartTrimEnd; decimalPlaces = Math.Min(decimalPlaces, fracPart.Length); } else fracPart = strs[1]; result = new Rational<T>(); try { string periodPart; bool periodFound = false; int i; for (i = 0; i < fracPart.Length; i++) { if (fracPart[i] == '0' && i != 0) continue; for (int j = i + 1; j < fracPart.Length; j++) { periodPart = fracPart.Substring(i, j - i); periodFound = true; decimal periodRepeat = 1; decimal periodStep = 1.0m / periodPart.Length; var upperBound = Math.Min(fracPart.Length, decimalPlaces); int k; for (k = i + periodPart.Length; k < upperBound; k += 1) { if (periodPart[(k - i) % periodPart.Length] != fracPart[k]) { periodFound = false; break; } periodRepeat += periodStep; } if (!periodFound && upperBound - k <= periodPart.Length && periodPart[(upperBound - i) % periodPart.Length] > '5') { var ind = (k - i) % periodPart.Length; var regroupedPeriod = (periodPart.Substring(ind) + periodPart.Remove(ind)).Substring(0, upperBound - k); ulong periodTailPlusOne = ulong.Parse(regroupedPeriod) + 1; ulong fracTail = ulong.Parse(fracPart.Substring(k, regroupedPeriod.Length)); if (periodTailPlusOne == fracTail) periodFound = true; } if (periodFound && periodRepeat >= minPeriodRepeat) { result = FromDecimal(strs[0], fracPart.Substring(0, i), periodPart); break; } else periodFound = false; } if (periodFound) break; } if (!periodFound) { if (fracPartTrimEnd.Length >= digitsForReal) return false; else { result = new Rational<T>(long.Parse(strs[0]), 1, false); if (fracPartTrimEnd.Length != 0) result = new Rational<T>(ulong.Parse(fracPartTrimEnd), TenInPower(fracPartTrimEnd.Length)); return true; } } return true; } catch { return false; } } public static Rational<T> FromDecimal(string intPart, string fracPart, string periodPart) { Rational<T> firstFracPart; if (fracPart != null && fracPart.Length != 0) { ulong denominator = TenInPower(fracPart.Length); firstFracPart = new Rational<T>(ulong.Parse(fracPart), denominator); } else firstFracPart = new Rational<T>(0, 1, false); Rational<T> secondFracPart; if (periodPart != null && periodPart.Length != 0) secondFracPart = new Rational<T>(ulong.Parse(periodPart), TenInPower(fracPart.Length)) * new Rational<T>(1, Nines((ulong)periodPart.Length), false); else secondFracPart = new Rational<T>(0, 1, false); var result = firstFracPart + secondFracPart; if (intPart != null && intPart.Length != 0) { long intPartLong = long.Parse(intPart); result = new Rational<T>(intPartLong, 1, false) + (intPartLong == 0 ? 1 : Math.Sign(intPartLong)) * result; } return result; } private static ulong TenInPower(int power) { ulong result = 1; for (int l = 0; l < power; l++) result *= 10; return result; } private static decimal TenInNegPower(int power) { decimal result = 1; for (int l = 0; l > power; l--) result /= 10.0m; return result; } private static ulong Nines(ulong power) { ulong result = 9; if (power >= 0) for (ulong l = 0; l < power - 1; l++) result = result * 10 + 9; return result; }
åŒã®ã³ã³ãã€ã«
åçŽå段éã®åŸãçµæã®ã»ãã³ãã£ãã¯ããªãŒãILã³ãŒãã«å€æããããã«ãMono.Cecilã䜿çšããŸããã
ããã»ã¹ã®éå§æã«ãã³ãã³ããèšè¿°ãããã¢ã»ã³ããªãã¯ã©ã¹ãããã³ã¡ãœãããäœæãããŸãã 次ã«ãåFuncNodeã«ã€ããŠãããã°ã©ã ã«è¡šç€ºãããåæ°ãèšç®ãããŸãã ããšãã°ãé¢æ°sinïŒx ^ 2ïŒ* cosïŒx ^ 2ïŒãããå Žåããã®äžã«xã2ã®ã¹ãä¹ããé¢æ°ã2åçºçããé¢æ°sinãšcosãäžåºŠã«1ã€ãã€çºçããŸãã å°æ¥ãé¢æ°èšç®ã®ç¹°ãè¿ãã«é¢ãããã®æ å ±ã¯ã次ã®ããã«äœ¿çšãããŸãïŒã€ãŸãããã®æ¹æ³ã§ã¯ã2çªç®ã®é¢æ°ã¯åãé¢æ°ã2åèšç®ããŸããïŒã
if (!func.Calculated) { EmitFunc(funcNode); func.Calculated = true; } else IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number));
ãã®ãã¹ãŠã®ã³ãŒããçæããåŸãäžã®å³ã«ç€ºãããã«ãILã³ãŒãã®ä»ã®æé©åãå¯èœã§ãã

ãã®åçã§ã¯ïŒ
- Ldarg-ç¹å®ã®é¢æ°åŒæ°ãã¹ã¿ãã¯ã«ããŒãããæäœã
- Ldc_R8-ç¹å®ã®doubleå€ãã¹ã¿ãã¯ã«ããŒãããŸãã
- Stloc.n-ã¹ã¿ãã¯ããæåŸã®å€ãååŸããããŒã«ã«å€æ°nã«ä¿åããŸãã
- Ldloc.n-ããŒã«ã«å€æ°n ãã¹ã¿ãã¯ã«ããã·ã¥ããŸãã
ç¹å®ã®æ¡ä»¶ãæºããããå ŽåãããŒãžã¥è²ã®ããã¯ã¹å ã®æ瀺ãåé€ã§ããŸãã ããšãã°ãå·Šäžã®ç»åã®å Žåã¯æ¬¡ã®ããã«èª¬æãããŸãïŒçŸåšã®åœä»€ãé¢æ°ããåŒæ°ãèªã¿èŸŒãã§ããããå®æ°ãèªã¿èŸŒãã§ããã次ã®åœä»€ããããããŒã«ã«å€æ°nã«ä¿åããŠããå ŽåãããŒã«ã«å€æ°nã®èªã¿èŸŒã¿åœä»€ãèªã¿èŸŒã¿ã§çœ®ãæããããšã«ããããã®åœä»€ã®ãããã¯ãåé€ã§ããŸãé¢æ°ã®åŒæ°ãŸãã¯å®æ°ã®èªã¿èŸŒã¿ã ããŒã«ã«å€æ°nã®æåã®saveã¹ããŒãã¡ã³ããŸã§çœ®æããã»ã¹ãç¶ããŸãã ä»ã®3ã€ã®ã±ãŒã¹ãåæ§ã«èª¬æãããŠããŸãã ããšãã°ãã·ãŒã±ã³ã¹Ldloc.n ; Stloc.nã¯ããã«åé€ã§ããŸãã
ãããã®æé©åã¯ãã³ãŒãã«åå²ããªãå Žåã«ãé©çšã§ããããšã«æ³šæãã䟡å€ããããŸããããã¯æããã§ãïŒå®å šã«æããã§ãªãå Žåã¯ãèããŠã¿ãããšããå§ãããŸãïŒã ããããç§ã®å Žåãæ°åŠé¢æ°ãšãã®å°é¢æ°ã®ã³ãŒãã«ã¯ãµã€ã¯ã«ãå«ããããšãã§ããªããããããã¯ãã¹ãŠæ©èœããŸãã
é«éã¹ãä¹
ç§ã¯ãã»ãšãã©èª°ãããåãçŽ æ©ãåã«äžããããã®ã¢ã«ãŽãªãºã ã«ã€ããŠç¥ã£ãŠãããšæããŸãã ãã ãã以äžã®ã¢ã«ãŽãªãºã ã¯ã³ã³ãã€ã«ã¬ãã«ã§è¡šç€ºãããŸãã
ILã³ãŒãã«å®è£
ãããé«éã¹ãä¹ã¢ã«ãŽãªãºã
if (power <= 3) { IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number)); for (int i = 1; i < power; i++) { IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Mul)); } } else if (power == 4) { IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Mul)); IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number)); IlInstructions.Add(new OpCodeArg(OpCodes.Mul)); } else { // result: funcNode.Number // x: funcNode.Number + 1 //int result = x; IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number + 1)); IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1)); power--; do { if ((power & 1) == 1) { IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1)); IlInstructions.Add(new OpCodeArg(OpCodes.Mul)); } if (power <= 1) break; //x = x * x; IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1)); IlInstructions.Add(new OpCodeArg(OpCodes.Ldloc, funcNode.Number + 1)); IlInstructions.Add(new OpCodeArg(OpCodes.Mul)); IlInstructions.Add(new OpCodeArg(OpCodes.Stloc, funcNode.Number + 1)); power = power >> 1; } while (power != 0); }
é«é环ä¹ã¢ã«ãŽãªãºã ã¯æé©ãªçŽ¯ä¹ã¢ã«ãŽãªãºã ã§ã¯ãªãããšã«æ³šæããŠãã ããã ããšãã°ã次ã®2ã€ã®æ¹æ³ã§åãå€æ°ã5åä¹ç®ããŸãã x ^ 4 + x ^ 3 + x ^ 2 + x = x *ïŒx *ïŒx *ïŒx + 1ïŒ+ 1ïŒ+ 1ïŒãªã©ã®æé©åãå®è£ ãããŠããŸããã
- var t = a ^ 2; a * a * a * a * a * a * a = t ^ 2 * t-éåžžã®ãé«éãã¢ã«ãŽãªãºã ã
- a * a * a * a * a * a * a =ïŒa ^ 3ïŒ^ 2-æé©ãªãé«éãã¢ã«ãŽãªãºã ã
ãšããã§ãéåžžã®åºå®æ°doubleã®å Žåãäžèšã®ä¹ç®ã®ç°ãªãé åºã§ã®ä¹ç®ã®çµæã¯ç°ãªãããšã«æ³šæããŠãã ããïŒã€ãŸãïŒa ^ 2ïŒ^ 2 * a ^ 2ïŒ=ïŒA ^ 3ïŒ^ 2 ïŒ ãã®ãããäžéšã®ã³ã³ãã€ã©ã¯ãããã®åŒã®å€ããæé©åããŸããã stackoverlofwã«ã¯ããã«é¢ããèå³æ·±ãQïŒAããããŸãã ãªãGCCã¯a * a * a * a * a * aãïŒa * a * aïŒ*ïŒa * a * aïŒã«æé©åããªãã®ã§ããïŒ ãããŠã ãªãMath.PowïŒxã2ïŒã¯x * xã³ã³ãã€ã©ãŒã«ãJITã«ãæé©åãããŠããªãã®ã§ãã ã
ããŒã«ã«å€æ°ã®æé©å
åã®æé ãããããããã«ãããŒã«ã«å€æ°ã¯ãå ã®åŒã§è€æ°åçºçãããã¹ãŠã®é¢æ°ã®çµæãæ ŒçŽããããã«äœ¿çšãããŸãã ããŒã«ã«å€æ°ãæäœããã«ã¯ã2ã€ã®åçŽãªåœä»€stlocãšldlocã®ã¿ã䜿çšãããŸãããããã¯ããã®ããŒã«ã«å€æ°ã®æ°ãæ åœãã1ã€ã®åŒæ°ã䜿çšããŸãã ãã ããããŒã«ã«å€æ°ã®æ°ããèšç®çµæãç¹°ãè¿ã衚瀺ããããã³ã«ïŒäœæããããã«ïŒã€ã³ã¯ãªã¡ã³ããããå ŽåãããŒã«ã«å€æ°ãå€æ°ååšããå¯èœæ§ããããŸãã ãã®åé¡ã軜æžããããã«ãããŒã«ã«å€æ°ã®ã©ã€ããµã€ã¯ã«ãå§çž®ããã¢ã«ãŽãªãºã ãå®è£ ãããŸããããã®ããã»ã¹ã¯äžã®å³ã«æ確ã«ç€ºãããŠããŸãã ã芧ã®ãšãããåŒã§ã¯5ã€ã®ããŒã«ã«å€æ°ã®ä»£ããã«3ã€ãã䜿çšã§ããŸããããã ãããã®ã貪欲ãªãã¢ã«ãŽãªãºã ã¯æé©ãªé åã§ã¯ãããŸããããå®è£ ããã¿ã¹ã¯ã«ã¯éåžžã«é©ããŠããŸãã
![]() | ![]() |
æªå®çŸ©ã®é¢æ°ãšãã®æŽŸçç©ã®ã³ã³ãã€ã«
éçºããã©ã€ãã©ãªã§ã¯ãfïŒxïŒãšãã圢åŒã®1ã€ã®å€æ°ã®åçŽãªé¢æ°ã ãã§ãªããfïŒxãaãbïŒxïŒïŒãªã©ã®ä»ã®å€æ°ã䜿çšã§ããŸããããã§ãaã¯æªç¥ã®å®æ°ã§ãbïŒxïŒã¯æªç¥ã®é¢æ°ã§ãããªã²ãŒããšããŠéä¿¡ãããŸãã ãåç¥ã®ããã«ãé¢æ°ã®å°é¢æ°ã®å®çŸ©ã¯æ¬¡ã®ãšããã§ãïŒbïŒxïŒ '=ïŒbïŒx + dxïŒ-bïŒxïŒïŒ/ dxã , :
ldarg.1 ldarg.0 callvirt TResult System.Func`2<System.Double,System.Double>::Invoke(T) ret
(dx = 0.000001)
ldarg.1 ldarg.0 ldc.r8 1E-06 add callvirt TResult System.Func`2<System.Double,System.Double>::Invoke(T) ldarg.1 ldarg.0 callvirt TResult System.Func`2<System.Double,System.Double>::Invoke(T) sub ldc.r8 0.000001 div ret
, , .
ãã¹ãäž
, MathFunction.Tests. WolframAlpha.NET .
WolframAlpha
WolframAlpha.NET â API wolframalpha . , , , , . :
public static bool CheckDerivative(string expression, string derivative) { return CheckEquality("diff(" + expression + ")", derivative); } public static bool CheckEquality(string expression1, string expression2) { WolframAlpha wolfram = new WolframAlpha(ConfigurationManager.AppSettings["WolframAlphaAppId"]); string query = "(" + expression1.Replace(" ", "") + ")-(" + expression2.Replace(" ", "") + ")"; QueryResult result = wolfram.Query(query); result.RecalculateResults(); try { double d; return double.TryParse(result.GetPrimaryPod().SubPods[0].Plaintext, out d) && d == 0.0; } catch { return false; } }
, , (MethodInfo):
Domain = AppDomain.CreateDomain("MathFuncDomain"); MathFuncObj = _domain.CreateInstanceFromAndUnwrap(FileName, NamespaceName + "." + ClassName); Type mathFuncObjType = _mathFuncObj.GetType(); Func = mathFuncObjType.GetMethod(FuncName); FuncDerivative = mathFuncObjType.GetMethod(FuncDerivativeName);
:
return (double)Func.Invoke(_mathFuncObj, new object[] { x })
:
if (_domain != null) AppDomain.Unload(Domain); File.Delete(FileName);
IL
IL , , C# csc.exe Release ,
x ^ 3 + sin(3 * ln(x * 1)) + x ^ ln(2 * sin(3 * ln(x))) - 2 * x ^ 3
csc.exe .NET 4.5.1 | MathExpressions.NET |
|
|
, C# ILSpy , , .. ã«
(ln(2 * sin(3 * ln(x))) * x ^ -1 + 3 * ln(x) * cos(3 * ln(x)) * sin(3 * ln(x)) ^ -1 * x ^ -1) * x ^ ln(2 * sin(3 * ln(x))) + 3 * cos(3 * ln(x)) * x ^ -1 + -(3 * x ^ 2)
double arg_24_0 = 2.0; double arg_1A_0 = 3.0; double num = Math.Log(x); double num2 = arg_1A_0 * num; double num3 = Math.Sin(num2); double num4 = Math.Log(arg_24_0 * num3); double arg_3B_0 = num4; double num5 = 1.0 / x; double arg_54_0 = arg_3B_0 * num5; double arg_4F_0 = 3.0 * num; num = Math.Cos(num2); return (arg_54_0 + arg_4F_0 * num / num3 * num5) * Math.Pow(x, num4) + num * num5 * 3.0 - x * x * 3.0;
, . , , , double arg_24_0 = 2.0; , .
, , , , , .
ãããã«
C#, , , - . , , OpenSource maxima lisp. , F# codeproject , , . , , , .
Github: source . : MathExpressions.NET . . - .
PS , . .
UPDATE: , , . , . .