Пример #1
0
        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));
        }
Пример #2
0
        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));
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }