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 override INumber Multiple(RuntimeData runtime, INumber val) { if (val is Number && (val as Number).Value == 1) { return(this.Clone()); } if (val is Number || val is Fraction) { if (this.Pow is Number && (this.Pow as Number).Value == 1) { AdditionFormula aa = new AdditionFormula(); foreach (var item in this.items) { aa.AddItem(runtime, item.Multiple(runtime, val)); } return(aa); } } else { MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, this); mf.AddItem(runtime, val); return(mf); } throw new NotImplementedException(); }
public override INumber Multiple(RuntimeData runtime, INumber val) { MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, val); mf.AddItem(runtime, this); return(mf); }
public override INumber Multiple(RuntimeData runtime, INumber val) { if (val is Fraction) { var f = val.Clone() as Fraction; f.Numerator = f.Numerator.Multiple(runtime, this); return(f); } if (val is Number && (val as Number).Value == 0) { return(Number.New(0)); } if (val is Number || val is Variable || val is Member) { var me = this.Clone() as MultipleFormula; me.AddItem(runtime, val); return(me); } else if (val is AdditionFormula) { var res = this.Clone() as MultipleFormula; res.AddItem(runtime, val); return(res); } else if (val is MultipleFormula) { var res = new MultipleFormula(); var v = val as MultipleFormula; for (int i = 0; i < this.items.Count; i++) { bool flag = false; for (int j = 0; j < v.items.Count; j++) { if (this.items[i].CanJoin(runtime, v.items[j])) { res.AddItem(runtime, this.items[i].Multiple(runtime, v.items[j])); flag = true; break; } } if (!flag) // ConJoinに引っかからなかった { res.AddItem(runtime, this.items[i]); } } return(res); } else { var me = this.Clone() as MultipleFormula; me.AddItem(runtime, val); return(me); } }
public override INumber Multiple(RuntimeData runtime, INumber val) { if (val is ImaginaryNumber) { Number res = Number.New(this.Value * (val as ImaginaryNumber).Value * -1); return(res); } MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, val); mf.AddItem(runtime, this); return(mf); }
public override INumber Integrate(RuntimeData runtime, string t) { INumber res = null; if (this.func is IIntegrateWithParameters) { res = (this.func as IIntegrateWithParameters).Integrate(runtime, t, this.param); // この段階ではpowのことは感がられていないので、pow部をここで処理する if (!(this.Pow is Number && (this.Pow as Number).Value == 1)) { throw new NotImplementedException("べき乗が1ではない関数の積分はまだ未対応です"); // 以下、微分のコードのコピペ MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, res); INumber pow = this.Clone(); pow.Pow = pow.Pow.Subtract(runtime, Number.New(1)); mf.AddItem(runtime, pow); res = mf; } if (runtime.Setting.DoOptimize) { res = res.Optimise(runtime); } } else { res = new FuncedINumber( runtime.Functions["intg"], new INumber[] { new Variable(new FuncCalc.Token(t, Analyzer.TokenType.Member)), this }); // たぶんpowの部分が怪しいのでチェックすること Debugger.Break(); } //最終処理部 { // resが結果だけど、べき乗部分の処理をしていないかもしれないので要チェック Debugger.Break(); if (!(this.Pow is Number && (this.Pow as Number).Value == 1)) { runtime.Setting.Logger.AddWarning("関数式の積分の部分は1以外のべき乗の計算を考慮していないので、結果がおかしくなっている可能性があります。"); } return(res); } }
public override INumber ExecuteDiff(RuntimeData runtime, string t) { INumber res = null; if (this.func is IDiffWithParameters) { res = (this.func as IDiffWithParameters).ExecuteDiff(runtime, t, this.param); // この段階ではpowのことは感がられていないので、pow部をここで処理する if (!(this.Pow is Number && (this.Pow as Number).Value == 1)) { MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, res); INumber pow = this.Clone(); pow.Pow = pow.Pow.Subtract(runtime, Number.New(1)); mf.AddItem(runtime, pow); res = mf; } if (runtime.Setting.DoOptimize) { res = res.Optimise(runtime); } } else { res = new FuncedINumber( runtime.Functions["diff"], new INumber[] { new Variable(new FuncCalc.Token(t, Analyzer.TokenType.Member)), this }); // たぶんpowの部分が怪しいのでチェックすること Debugger.Break(); } //最終処理部 { var mf = Runtime.Func.Differential.DiffPow(runtime, t, this); if (mf != null) { mf.AddItem(runtime, res); return(mf); } else { return(res); } } }
public override INumber ExecuteDiff(RuntimeData runtime, string t) { MultipleFormula mf = Runtime.Func.Differential.DiffPow(runtime, t, this); var res = this.Eval(runtime).ExecuteDiff(runtime, t); if (mf != null) { mf.AddItem(runtime, res); return(mf); } else { return(res); } }
public override INumber Multiple(RuntimeData runtime, INumber val) { if (val is IConstParameter) { var me = this.Clone() as FloatNumber; me.value *= (val as IConstParameter).ConstValue; return(me); } if (val is InfinityValue) { return(val.Multiple(runtime, this)); } MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, val); mf.AddItem(runtime, this); return(mf); }
public override INumber Multiple(RuntimeData runtime, INumber val) { if (val.ValueType == ValueType.Plus) { return(this == InfinityValue.value ? InfinityValue.value : InfinityValue.minusvalue); } else if (val.ValueType == ValueType.Minus) { return(this == InfinityValue.value ? InfinityValue.minusvalue : InfinityValue.value); } else // val.ValueType == ValueType.Unknown { if (val is MultipleFormula) { var res = this; MultipleFormula mf = new Expression.MultipleFormula(); for (int i = 0; i < (val as MultipleFormula).Items.Count; i++) { var item = (val as MultipleFormula).Items[i]; if (item.ValueType == ValueType.Minus) { res = (res == InfinityValue.value) ? InfinityValue.minusvalue : InfinityValue.value; } if (item.ValueType == ValueType.Unknown) { mf.AddItem(runtime, item); } } mf.AddItem(runtime, res); return(mf); } else { MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, this); mf.AddItem(runtime, val); return(mf); } } }
public override INumber Power(RuntimeData runtime, INumber val) { if (val is Number) { var pow = val as Number; if (pow.Value == 0) { return(Number.New(1)); } if (pow.Value < 0) // 乗数がマイナスだったら { var res = this.Clone(); res = res.Power(runtime, Number.New(pow.Value * -1)); return(new Fraction(res, Number.New(1))); } if (pow.Value % 2 == 0) // 乗数が偶数だったら { if (pow.Value % 4 == 0) { return(Number.New(this.Value).Power(runtime, pow)); } else { return(Number.New(this.Value).Power(runtime, pow).Multiple(runtime, Number.New(-1))); } } else { MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, Number.New(this.Value).Power(runtime, Number.New(pow.Value - 1))); mf.AddItem(runtime, this); return(mf); } } throw new NotImplementedException("虚数に数値以外のべき乗含むのはまだ実装していません。"); }
public override INumber Optimise(RuntimeData runtime) { var me = this.Clone() as Fraction; // [分母][分子]が分数の場合は有理化する if (me.Denominator is Fraction && me.Numerator is Fraction) { me = new Fraction( (me.Denominator as Fraction).Numerator.Multiple(runtime, (me.Numerator as Fraction).Denominator), (me.Denominator as Fraction).Denominator.Multiple(runtime, (me.Denominator as Fraction).Numerator) ); } else if (me.Denominator is Fraction) { me = new Fraction( (me.Denominator as Fraction).Numerator, (me.Denominator as Fraction).Denominator.Multiple(runtime, me.Numerator) ); } else if (me.Numerator is Fraction) { me = new Fraction( me.Denominator.Multiple(runtime, (me.Numerator as Fraction).Denominator), (me.Numerator as Fraction).Numerator ); } // 分母が0だったら無限を返す if (me.Denominator.Eval(runtime).Equals(runtime, Number.New(0))) { if (me.Numerator.ValueType == ValueType.Plus) { return(InfinityValue.PlusValue); } else if (me.Numerator.ValueType == ValueType.Minus) { return(InfinityValue.MinusValue); } else { MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, this.Numerator); mf.AddItem(runtime, InfinityValue.PlusValue); return(mf); ; } } if (me.Numerator is Number && me.Denominator is Number) { // 最大公約数を求めて分母分子を割る var func = runtime.Functions.Where( f => f.Key == "gcd" && f.Value.Parameter[0] == ExpressionType.Number && f.Value.Parameter[1] == ExpressionType.Number); var res = func.First().Value.Execute(runtime, me.Denominator, me.Numerator); me.Denominator = me.Denominator.Divide(runtime, res); me.Numerator = me.Numerator.Divide(runtime, res); } else if (me.Denominator is MultipleFormula && this.Numerator is Variable) { bool dv_res; INumber dr_res; dr_res = (me.Denominator as MultipleFormula).TryDivide(runtime, me.Numerator, out dv_res); if (dv_res) { me.Numerator = Number.New(1); me.Denominator = dr_res; } else { } } else if (me.Denominator is MultipleFormula && me.Numerator is MultipleFormula) { for (int i = 0; i < (me.Numerator as MultipleFormula).Count; i++) { var dt = (me.Numerator as MultipleFormula).Items[i]; bool dv_res; var r = (me.Denominator as MultipleFormula).TryDivide(runtime, dt, out dv_res); if (dv_res) { me.Denominator = r; (me.Numerator as MultipleFormula).Items.RemoveAt(i); i--; } else { } } } // 分母分子を最適化する me.Denominator = me.Denominator.Optimise(runtime); me.Numerator = me.Numerator.Optimise(runtime); // メンバーを含む式で約分できるか確かめる if (me.Numerator is MultipleFormula && me.Numerator.Pow.Equals(runtime, Number.New(1)) && me.Denominator is MultipleFormula && me.Denominator.Pow.Equals(runtime, Number.New(1))) { var den = me.Denominator as MultipleFormula; bool flag = false; for (int i = 0; i < (me.Numerator as MultipleFormula).Count; i++) { bool res; var fm = den.TryDivide(runtime, (me.Numerator as MultipleFormula).Items[i], out res); if (res) { flag = true; me.Denominator = den; if (fm is MultipleFormula) { den = fm as MultipleFormula; } else { break; } (me.Numerator as MultipleFormula).Items.RemoveAt(i); i--; } } } // 分母が1だったら分子部分だけを返す if (me.Denominator.Equals(runtime, Number.New(1))) { return(me.Numerator); } return(me); }
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); }