public override bool Equals(RuntimeData runtime, INumber val) { if (val is Number) { var me = this.Optimise(runtime); if (me is Number && me.Equals(runtime, val)) { return(true); } return(false); } if (val is Fraction) { INumber f1 = this.Optimise(runtime); INumber f2 = (val as Fraction).Optimise(runtime); if (f1 is Fraction && f2 is Fraction && (f1 as Fraction).Denominator.Equals(runtime, (f2 as Fraction).Denominator) && (f1 as Fraction).Numerator.Equals(runtime, (f2 as Fraction).Numerator)) { return(true); } if (f1 is Number && f2 is Number && f1.Equals(runtime, f2)) { return(true); } if ((f1 is Number && f2 is Fraction) || (f1 is Fraction && f2 is Number)) { return(false); } return(f1.Equals(runtime, f2)); } return(val.Equals(runtime, this)); }
public override bool Equals(RuntimeData runtime, INumber val) { if (val is Number) { return(this._value == (val as Number).Value); } if (val is Fraction) { return((val as Fraction).Optimise(runtime).Equals(val)); } return(val.Equals(runtime, this)); }
/// <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 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)); }
public INumber ExecuteDiff(RuntimeData runtime, string t, INumber[] parameters) { // log(xy) => log(x) + log(y) if (parameters[1] is MultipleFormula) { AdditionFormula af = new Expression.AdditionFormula(); foreach (var item in (parameters[1] as MultipleFormula).Items) { af.AddItem(runtime, this.ExecuteDiff(runtime, t, new INumber[] { parameters[0], item })); } return(af); } if (parameters[1] is Fraction) { AdditionFormula af = new Expression.AdditionFormula(); Fraction f = parameters[1] as Fraction; af.AddItem(runtime, this.ExecuteDiff(runtime, t, new INumber[] { parameters[0], f.Numerator })); af.AddItem(runtime, this.ExecuteDiff(runtime, t, new INumber[] { parameters[0], f.Denominator }).Multiple(runtime, Number.New(-1))); return(af); } // 普通のlogの微分 if (parameters[0] is NaturalLogarithm) { NaturalLogarithm e = parameters[0] as NaturalLogarithm; if (e.Pow.Equals(runtime, Number.New(1))) { var prm = parameters[1].ExecuteDiff(runtime, t); if (prm.Equals(runtime, Number.New(0)) || prm.Equals(runtime, Number.New(1))) { return(new Fraction( parameters[1], Number.New(1))); } else { MultipleFormula mf = new Expression.MultipleFormula(); mf.AddItem(runtime, prm); mf.AddItem(runtime, new Fraction( parameters[1], Number.New(1))); return(mf); } } } else if (!FuncCalc.Runtime.Func.Differential.IsConstValue(runtime, parameters[0])) { throw new RuntimeException("底に定数以外が含まれたlogの微分を行うことはできません。"); } INumber param1Diff = parameters[1].ExecuteDiff(runtime, t); if (param1Diff.Equals(runtime, Number.New(0))) { param1Diff = Number.New(1); } MultipleFormula den = new MultipleFormula(); den.AddItem(runtime, parameters[1]); den.AddItem(runtime, new FuncedINumber(this, new INumber[] { new NaturalLogarithm(), parameters[0] })); Fraction res = new Fraction(den, param1Diff); return(res); }