public override INumber Subtract(RuntimeData runtime, INumber val) { var v = val.Eval(runtime); if (v is Number) { if (this.Pow.Equals(runtime, val.Pow)) { return(Number.New(this.Value - (val as Number).Value)); } else { AdditionFormula af = new Expression.AdditionFormula(); af.AddItem(runtime, this); af.AddItem(runtime, val.Multiple(runtime, Number.New(-1))); return(af); } } if (v is Fraction) { return(v.Multiple(runtime, Number.New(-1)).Add(runtime, this)); } return(v.Subtract(runtime, this)); }
public INumber Execute(RuntimeData runtime, INumber left, INumber right) { if (!(left is Variable) && !(left is Member) && !(left is FunctionFormula)) { throw new SyntaxException("代入は変数にのみ行えます。", left); } Variable v = null; if (left is Variable) { v = left as Variable; } else if (left is Member) { v = new Variable((left as Member).Token); } else if (left is FunctionFormula && (left as FunctionFormula).Count == 1) { v = new Variable(((left as FunctionFormula).Items[0] as Member).Token); } else { throw new NotImplementedException(); } var res = right.Eval(runtime); runtime.SetVariable(runtime, v, res); return(res); }
public static bool IsConstValue(RuntimeData runtime, INumber num) { var res = num.Eval(runtime); if (res is IConstParameter) { return(true); } if (res is AdditionFormula || res is MultipleFormula) { for (int i = 0; i < (res as IFormula).Count; i++) { if (!((res as IFormula).Items[i] is IConstParameter)) { return(false); } } return(true); } if (res is Fraction) { return (IsConstValue(runtime, (res as Fraction).Denominator) && IsConstValue(runtime, (res as Fraction).Numerator)); } return(false); }
public override INumber Multiple(RuntimeData runtime, INumber val) { if (this.Value == 0) { return(Number.New(0)); } var v = val.Eval(runtime); if (v is Number) { if (this.Pow.Equals(runtime, val.Pow)) { return(Number.New(this.Value * (v as Number).Value)); } else { MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, this); mf.AddItem(runtime, val); return(mf); } } return(val.Multiple(runtime, this)); }
public override INumber Multiple(RuntimeData runtime, INumber val) { var v = val.Eval(runtime); if (v is Variable && (v as Variable).Name == this.Name) { var me = this.Clone() as Variable; me.multi = me.multi.Multiple(runtime, (v as Variable).multi); me.Pow = me.Pow.Add(runtime, (v as Variable).Pow); return(me); } if (v is Number && (v as Number).Value == 1) { return(this); } if (v is Number) { var me = this.Clone() as Variable; me.multi = me.multi.Multiple(runtime, v); return(me); } return(v.Multiple(runtime, this)); MultipleFormula af = new MultipleFormula(); af.AddItem(runtime, this); af.AddItem(runtime, v); return(af); }
public INumber Execute(RuntimeData runtime, INumber left, INumber right) { var r = right.Eval(runtime); runtime.Setting.GetOperator("?=", null, true).Execute(runtime, left, r); return(r); }
public INumber Execute(RuntimeData runtime, INumber left, INumber right) { var dt = left.Eval(runtime); runtime.Setting.Spec.Operations.Where(a => a.Key.GetType() == typeof(Substitution)).First().Key .Execute(runtime, left, left.Add(runtime, Number.New(1))); return(dt); }
public override INumber Divide(RuntimeData runtime, INumber val) { var v = val.Eval(runtime); if (val is Number && (val as Number).Value == 0) { if (this.ValueType == ValueType.Plus) { return(InfinityValue.PlusValue); } else { return(InfinityValue.MinusValue); } // ValueType.Unknownになることはない } if (v is Number) { if (this.Pow.Equals(runtime, val.Pow)) { if (this.Value % (v as Number).Value == 0) // 割り切れるなら数値として返す { return(Number.New(this.Value / (v as Number).Value)); } else // 割り切れないなら分数として返す { return(new Fraction(v, this)); } } else { return(new Fraction(v, this)); } } if (v is Fraction) { return ((new Fraction((v as Fraction).Numerator, (v as Fraction).Denominator)).Multiple(runtime, this)); } // こちらの方で対応していないものも半ば強引に解決させる return(new Fraction(val, this)); }
public void AddItem(RuntimeData runtime, INumber val) { var v = val.Eval(runtime); if (v is Number && (val as Number).Value == 0) { } else if (v is AdditionFormula && (v.Pow is Number && (v.Pow as Number).Value == 1)) { foreach (var item in (val as AdditionFormula).items) { this.items.Add(item); } } else { this.items.Add(v); } }
public void AddItem(RuntimeData runtime, INumber val) { var v = val.Eval(runtime); if (v is Number && (v as Number).Value == 1) { return; } if (val is AdditionFormula && (val as AdditionFormula).Count == 1) { this.AddItem(runtime, (val as AdditionFormula).Items[0]); return; } if (val is MultipleFormula) { foreach (var item in (val as MultipleFormula).items) { this.AddItem(runtime, item); } return; } for (int i = 0; i < this.items.Count; i++) { if (runtime.Setting.DoOptimize && ( this.items[i].CanJoin(runtime, val) || val.CanJoin(runtime, this.items[i]))) { this.items[i] = this.items[i].Multiple(runtime, val); return; } } this.items.Add(v); }
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 INumber TryDivide(RuntimeData runtime, INumber val, out bool result) { // IConstParameterで割ろうとした場合はBase.Divideでも対応できるのでここでは割愛する // メンバー(変数)で割ろうとした場合 Variable v = val as Variable; if (v != null || (v = val.Eval(runtime) as Variable) is Variable) { var me = this.Clone() as MultipleFormula; for (int i = 0; i < me.items.Count; i++) { var item = me.items[i]; if (item is MultipleFormula) { throw new FuncCalcException("MultipleFormulaの中にMultipleFormulaが含まれています。", this); } if (item is Variable) { var res = item.Divide(runtime, v); if (res is Number && (res as Number).Value == 1) { me.items.RemoveAt(i); result = true; return(me); } me.items[i] = res; result = true; return(me); } } } if (val is MultipleFormula) { MultipleFormula den = new Expression.MultipleFormula(); INumber num = this.Clone() as MultipleFormula; MultipleFormula f = val as MultipleFormula; bool flag = false; for (int i = 0; i < f.items.Count; i++) { var ex = f.items[i]; bool dv_res; INumber res; res = (num as MultipleFormula).TryDivide(runtime, ex, out dv_res); if (dv_res) { flag = true; if (res is MultipleFormula) { num = res as MultipleFormula; } else { num = res; for (int j = i + 1; j < f.items.Count; j++) { den.AddItem(runtime, f.items[j]); } break; } } else { den.AddItem(runtime, ex); } } if (!flag) { result = false; return(null); } else { result = true; // numの条件判定はdenより先に行う if (num is MultipleFormula) { INumber d = den; if (den.items.Count == 0) { return(num); } if (den.items.Count == 1) { d = den.items[0]; } if ((num as MultipleFormula).items.Count == 0) { return(new Fraction(d, Number.New(1))); } if ((num as MultipleFormula).items.Count == 1) { return(new Fraction(d, (num as MultipleFormula).items[0])); } } // 最低限の形で返す if (den.items.Count == 0) { return(num); } if (den.items.Count == 1) { var res = new Fraction(den.items[0], num); if (runtime.Setting.DoOptimize) { return(res.Optimise(runtime)); } else { return(res); } } return(new Fraction(den, num)); } } result = false; return(null); }