public override INumber Execute(RuntimeData runtime, params INumber[] parameters) { runtime.AddBlock(new BlockData()); var res = parameters[1].Eval(runtime); res = res.Optimise(runtime); parameters[0].Eval(runtime); res = res.Eval(runtime); runtime.PopBlock(); return(res); }
/// <summary> /// 二次方程式を解決する /// </summary> private INumber SolutionQuadraticEquation(RuntimeData runtime, string varname, Dictionary <int, INumber> keisu) { if (!(keisu.Keys.Where(k => k >= 3).Count() == 0 && // x^3のような大きなべき乗がない keisu.Values.Where(v => !(v is IConstParameter)).Count() == 0 && // 係数が全て実数である keisu.ContainsKey(2) && // x^2が含まれている !(keisu[2] is Number && (keisu[2] as Number).Value == 0))) // x^2の係数が0ではない { return(null); } runtime.AddLogWay("AsQuadraticEquation", keisu[2], keisu[1], keisu[0]); INumber res1 = null, res2 = null; try { runtime.AddBlock(new BlockData() { MoreScope = false }); runtime.NowBlock.Variables.Add("a", keisu[2]); runtime.NowBlock.Variables.Add("b", keisu[1]); runtime.NowBlock.Variables.Add("c", keisu[0]); // ( -b ± √(b^2 - 4ac)) / 2a res1 = (runtime.Setting.GetExpression("((0-b)+sqrt(b^2-4a*c))/(2a)") as IEval).Eval(runtime); res2 = (runtime.Setting.GetExpression("((0-b)-sqrt(b^2-4a*c))/(2a)") as IEval).Eval(runtime); var vr = new Variable(varname); runtime.AddLogWay("_QuadraticEquationWay1", vr, res1); runtime.AddLogWay("_QuadraticEquationWay2", vr, res2); } finally { runtime.PopBlock(); } if (res1 == null && res2 == null) { return(null); } Results ress = new Results(new Variable(varname)); ress.items.Add(res1); if (!res1.Equals(runtime, res2)) { ress.items.Add(res2); } return(ress); }
public override INumber Execute(RuntimeData runtime, params INumber[] parameters) { if (this.name == "#userDefine") { throw new RuntimeException("この関数をそのまま呼び出すことはできません。"); } runtime.AddBlock(new BlockData()); for (int i = 0; i < parameters.Length; i++) { var exp = parameters[i]; runtime.SetVariable(runtime, new Variable(new Token(this._paramName[i], Analyzer.TokenType.Member)), exp.Eval(runtime)); } var res = this.formula.Eval(runtime); runtime.PopBlock(); return(res); }
public INumber Eval(RuntimeData runtime) { BlockData data = runtime.NowBlock; for (int i = 0; i < this.Count; i++) { IExpression exp = this.Items[i]; if (exp is Operator) { INumber left = null, right = null; Operator op = exp as Operator; if (runtime.Setting.IsDebug) { // Console.Clear(); OutputStackData(runtime, exp); } bool willEval = true; // 後ろの方にEvalせずに実行する演算子がある場合、変数を評価しないようにする for (int j = i + 1; j < this.Count; j++) { if (this.items[j] is Operator && !(this.items[j] as Operator).Evaluator.DoEvaledParam) { willEval = false; runtime.AddBlock(new BlockData() { MoreScope = false }); if (runtime.Setting.IsDebug) { Console.WriteLine("AddBlock[MoreScope=false] しました"); } break; } } if (op.Evaluator.RequireRightParameter) { var r = data.Pop(); if (op.Evaluator.DoEvaledParam && willEval) { r = (r as IEval).Eval(runtime); } if (!op.Evaluator.DoEvaledParam && r is INumber) { } else if (r is Variable || r is Member) { } else if (r is Member) { r = (r as Member).GetVariable(runtime); } else { r = (r as IEval).Eval(runtime); } right = r as INumber; if (op.Evaluator.DoEvaledParam && willEval) { right = right.Eval(runtime); } } if (op.Evaluator.RequireLeftParameter) { var l = data.Pop(); if (op.Evaluator.DoEvaledParam && willEval) { l = (l as IEval).Eval(runtime); } if (!op.Evaluator.DoEvaledParam && l is INumber) { } else if (l is Variable) { } else if (l is Member) { l = (l as Member).GetVariable(runtime); } else { l = (l as IEval).Eval(runtime); } left = l as INumber; if (op.Evaluator.DoEvaledParam && willEval) { left = left.Eval(runtime); } } var res = (exp as Operator).Evaluator.Execute(runtime, left as INumber, right as INumber); if (res != null && runtime.Setting.DoOptimize) { res = res.Optimise(runtime); } if (!willEval) { runtime.PopBlock(); } data.Push(res); if (runtime.Setting.IsDebug) { // Console.Clear(); Console.WriteLine("Eval RPE Formula : ({0})[{1}] {2} ({3})[{4}] => {5}[{6}]", left != null ? left.ToString() : "null", left != null ? left.GetType().Name : "", (exp as Operator).Evaluator.Name, right != null ? right.ToString() : "null", right != null ? right.GetType().Name : "", res != null ? res.ToString() : "null", res != null ? res.GetType().Name : ""); OutputStackData(runtime, null); } } else { if (exp is IEval) { data.Push(exp as IEval); } else { throw new NotImplementedException(); } } } if (data.Count == 0) { return(null); } else { var result = data.Pop() as INumber; if (result != null && runtime.Setting.DoOptimize) { return(result.Optimise(runtime)); } return(result); } }
public override INumber Eval(RuntimeData runtime) { // 1しかない場合は変数 if (this.items.Count == 1) { if (!(this.items[0] is INumber)) { throw new NotImplementedException("FunctionFormulaに値以外が紛れ込んでいます"); } return((this.items[0] as INumber).Eval(runtime)); } bool nextFlag = false; IExpression func = null; INumber multiple = Number.New(1); for (int i = 0; i < this.items.Count; i++) { IExpression ex = this.items[i]; if (ex is Member && ((nextFlag && func != null) || (!nextFlag && func == null))) { func = FunctionFormula.GetMember(runtime, func, ex as Member); if (func == null) { throw new SyntaxException(string.Format("'{0}'は見つかりませんでした", ex.Token.Text), ex.Token, new KeyNotFoundException()); } if (func is INumber && !(func is IEvalWithParameters)) { multiple = multiple.Multiple(runtime, func as INumber); func = null; } nextFlag = false; continue; } if (ex is Operator && ex.Token.Text == runtime.Setting.Spec.ScopeOperator) { nextFlag = true; continue; } // パラメータ関係 if ((ex is IFormula) && !nextFlag) { if (func == null && multiple is IEvalWithParameters) { func = multiple; multiple = Number.New(1); } if (func != null) { runtime.AddBlock(new BlockData() { MoreScope = true }); runtime.NowBlock.Push(new LineBreak()); (ex as IFormula).ExecuteAsParameter(runtime); IExpression res = null; if (func is INumber && func is IEvalWithParameters) { List <INumber> prm = new List <INumber>(); for (; runtime.NowBlock.Stack.Length != 0;) { var it = runtime.NowBlock.Pop(); if (it is LineBreak) { continue; } if (!(it is INumber)) { throw new RuntimeException("インデックス指定で値型(INumber)以外のパラメータを指定することはできません。", it); } prm.Add(it as INumber); } res = (func as IEvalWithParameters).Execute(runtime, prm.ToArray()) as IExpression; } else { res = ExecuteFunc(runtime, func, multiple); } runtime.PopBlock(); if (res is INumber) { if (multiple is Number && (multiple as Number).Value != 1) { multiple = multiple.Multiple(runtime, res as INumber); } else { multiple = res as INumber; } func = null; } else if (res == null) { func = null; multiple = null; } else { func = res; throw new NotImplementedException("関数の戻り値は現在 '値' しか対応していません"); } continue; } else { if (multiple.Equals(runtime, Number.New(1))) { return(this); // 未解決のメンバーを実行しようとしている式は評価せずに返す } else { var res = (ex as IFormula).Eval(runtime); multiple = multiple.Multiple(runtime, res); } continue; } } throw new NotImplementedException(); } if (func == null && multiple == null) { return(null); } if (func == null) { return(multiple); } if (!(func is INumber)) { throw new RuntimeException("現在、関数の戻り値は値のみに対応しています。関数ポインターを戻り値にすることはできません。", this); } return((func as INumber).Eval(runtime)); }