Beispiel #1
0
        /// <summary>
        /// 分数を簡単にする
        /// </summary>
        private void Reduction()
        {
            var factor = Factorizations.GCD((long)Numerator, (long)Denominator);

            Numerator   = Numerator / (ulong)factor;
            Denominator = Denominator / (ulong)factor;
        }
        /// <summary>
        /// 多項式が整理できる場合は整理する
        /// ・分母分子ごとに同類項をまとめる
        /// ・共通因数があれば求める
        /// ・共通因数を掛けて約分し、それを分母分子に分けて掛ける
        /// </summary>
        private void Initialise()
        {
            if (NumMonof.IsZero())
            {
                DenMonof = new List <Monomial> {
                    1
                };
                return;
            }
            if (NumMonof.IsOne() && DenMonof.IsOne())
            {
                return;
            }

            //0の項を削除
            NumMonof = NumMonof.Where(x => !x.IsZero()).ToList();
            DenMonof = DenMonof.Where(x => !x.IsZero()).ToList();

            //同類項をまとめる
            var SortedNumerator = NumMonof.Grouping(IsNumberKey: false).Select(x =>
            {
                var res = x[0];

                res.Number = x.Select(y => y.Number).Aggregate((now, next) => now + next);

                return(res);
            }).ToList();
            var SortedDenominator = DenMonof.Grouping(IsNumberKey: false).Select(x =>
            {
                var res = x[0];

                res.Number = x.Select(y => y.Number).Aggregate((now, next) => now + next);

                return(res);
            }).ToList();

            if (SortedNumerator.IsOne() || SortedDenominator.IsOne())
            {
                NumMonof = SortedNumerator;
                DenMonof = SortedDenominator;
                return;
            }

            var NumFactor = Factorizations.FactorOut(SortedNumerator);
            var DenFactor = Factorizations.FactorOut(SortedDenominator);

            Monomial Factor = NumFactor.Item1 / DenFactor.Item1;

            NumMonof = NumFactor.Item2.Select(x => x * Factor.GetNumerator()).ToList();
            DenMonof = DenFactor.Item2.Select(x => x * Factor.GetDenominator()).ToList();

            Reduction();

            Trace.WriteLine("Formula Initialized:" + this.GetString());
        }
        /// <summary>
        /// 約分する
        /// </summary>
        private void Reduction()
        {
            var factors = Factorizations.FactorOut(this);

            NumMonof = (factors.Item1.GetNumerator() * factors.Item2.GetNumerator()).NumMonof;
            DenMonof = (factors.Item1.GetDenominator() * factors.Item2.GetDenominator()).NumMonof;

            if (DenMonof.Count() == 1)//分母が一つだけであれば数字は上につける
            {
                NumMonof           = NumMonof.Select(x => x / DenMonof[0].Number.ToDouble()).ToList();
                DenMonof[0].Number = 1;
                return;
            }
            else//上下の式がどちらかの因数である場合は、割り切る
            {
                var  chars  = this.GetCharDics().Keys.ToList();
                char target = '0';
                if (chars.Count() == 0)
                {
                    return;
                }
                if (chars.Count() == 1)
                {
                    target = chars[0];
                }
                else
                {
                    var chardic = chars.ToDictionary(x => x, x => NumMonof.Concat(DenMonof).Max(y => y.Character.ContainsKey(x) ? y.Character[x] : 0));
                    target = chardic.First().Key;
                    foreach (var dic in chardic)
                    {
                        if (dic.Key != target)
                        {
                            if (dic.Value > chardic[target])
                            {
                                target = dic.Key;
                            }
                            else if (dic.Value == chardic[target])
                            {
                                if (dic.Key.CompareTo(target) < 0)
                                {
                                    target = dic.Key;
                                }
                            }
                        }
                    }
                }

                var IsNumBigger = NumMonof.Max(x => x.Character.ContainsKey(target) ? x.Character[target] : 0)
                                  > DenMonof.Max(x => x.Character.ContainsKey(target) ? x.Character[target] : 0);


                var Bigger   = new Dictionary <int, List <Monomial> > {
                };
                var Smaller  = new Dictionary <int, List <Monomial> > {
                };
                var BiggerF  = new List <Monomial> {
                };
                var SmallerF = new List <Monomial> {
                };


                if (IsNumBigger)
                {
                    BiggerF  = NumMonof;
                    SmallerF = DenMonof;

                    Bigger  = NumMonof.GroupBy(x => x.Character.ContainsKey(target) ? x.Character[target] : 0).ToDictionary(x => x.Key, x => x.Select(y => y).ToList());
                    Smaller = DenMonof.GroupBy(x => x.Character.ContainsKey(target) ? x.Character[target] : 0).ToDictionary(x => x.Key, x => x.Select(y => y).ToList());
                }
                else
                {
                    BiggerF  = DenMonof;
                    SmallerF = NumMonof;

                    Bigger  = DenMonof.GroupBy(x => x.Character.ContainsKey(target) ? x.Character[target] : 0).ToDictionary(x => x.Key, x => x.Select(y => y).ToList());
                    Smaller = NumMonof.GroupBy(x => x.Character.ContainsKey(target) ? x.Character[target] : 0).ToDictionary(x => x.Key, x => x.Select(y => y).ToList());
                }

                if (Smaller.Any(x => x.Value.Count() != 1))
                {
                    return;
                }

                var SUMfactor = new List <Monomial> {
                };


                var BiggerMax  = Bigger.Keys.Max();
                var SmallerMax = Smaller.Keys.Max();

                while (true)
                {
                    var factor = Bigger[BiggerMax].Select(x => x / Smaller[SmallerMax][0]).ToList();
                    SUMfactor = SUMfactor.Concat(factor).ToList();

                    BiggerF   = (new Formula(BiggerF) - new Formula(SmallerF) * new Formula(factor)).NumMonof;
                    Bigger    = BiggerF.GroupBy(x => x.Character.ContainsKey(target) ? x.Character[target] : 0).ToDictionary(x => x.Key, x => x.Select(y => y).ToList());
                    BiggerMax = Bigger.Keys.Max();

                    if (BiggerF.Count() == 0)
                    {
                        var res = new Formula(SUMfactor);

                        NumMonof = res.NumMonof;
                        DenMonof = res.DenMonof;

                        return;
                    }
                    else if (BiggerMax < SmallerMax)
                    {
                        return;
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// ある文字で式を整理する(x =の形にする)
        /// </summary>
        /// <param name="LeftSide">左辺</param>
        /// <param name="RightSide">右辺</param>
        /// <param name="target">文字</param>
        /// <returns></returns>
        public async static Task <List <Formula> > SolveAboutX(Formula LeftSide, Formula RightSide, char target)
        {
            //分母部分を無くす
            var L = LeftSide.GetNumerator() * RightSide.GetDenominator();
            var R = RightSide.GetNumerator() * LeftSide.GetDenominator();

            //単項式の分母部分をなくす
            var LcommonFactor = Factorizations.FactorOut(L);
            var RcommonFactor = Factorizations.FactorOut(R);

            L = LcommonFactor.Item2 * LcommonFactor.Item1.GetNumerator() * RcommonFactor.Item1.GetDenominator();
            R = RcommonFactor.Item2 * RcommonFactor.Item1.GetNumerator() * LcommonFactor.Item1.GetDenominator();

            //xを含む単項式と含まないものに分け、左辺に含むものを集める
            var Lx       = L.NumMonof.Where(x => x.GetCharDics().ContainsKey(target));
            var Lexceptx = L.NumMonof.Where(x => !x.GetCharDics().ContainsKey(target));

            var Rx       = R.NumMonof.Where(x => x.GetCharDics().ContainsKey(target));
            var Rexceptx = R.NumMonof.Where(x => !x.GetCharDics().ContainsKey(target));

            L = new Formula(Lx.Concat(Rx.Select(x => - x)).ToList());
            R = new Formula(Lexceptx.Select(x => - x).Concat(Rexceptx).ToList());

            //Xがどのようなものなのかを調べる
            var XInfo  = L.GetTargetCharInfo(target);
            var XTypes = XInfo.NumMonof.Select(x =>
            {
                if (x.NthRoots.Count() > 0)
                {
                    return(x, -Factorizations.LCM(x.NthRoots.Keys.ToList()));
                }
                else
                {
                    return(x, x.Character[target]);
                }
            }).GroupBy(x => x.Item2).ToDictionary(x => x.Key, x => x.Select(y => y.Item1).ToList());

            bool IsRightZero = R.IsZero();

            if (XInfo.NumMonof.Any(x => x.NumFuncs.Count() != 0 || x.DenFuncs.Count() != 0))//関数部に文字列がある場合
            {
                throw new Exception(AppResources.VariablesInFunction);
            }
            else if (XTypes.Count() > 4 || (IsRightZero && XTypes.Count() >= 3))//三次方程式以上の場合は解けない
            {
                throw new Exception(AppResources.TooComplicatedX);
            }
            else if (XTypes.Count() == 1)//xの種類が1の場合
            {
                if (IsRightZero && XTypes.All(x => x.Key > 0))
                {
                    return new List <Formula> {
                               (Formula)0
                    }
                }
                ;

                if (!XTypes.Any(x => x.Key < 0))
                {
                    R = R / L * new Monomial(1.0, new Dictionary <char, int> {
                        { target, XTypes.Keys.First() }
                    });

                    return(new List <Formula> {
                        Formula.CalcRoot(R, XTypes.First().Key)
                    });
                }
                else
                {
                    if (XTypes.First().Value.Count() >= 3)//3つ以上
                    {
                        throw new Exception(AppResources.TooComplicatedX);
                    }
                    else if (XTypes.First().Value.Count() == 1)//1つ
                    {
                        if (XTypes.First().Key > 0)
                        {
                            L = Formula.CalcRoot(L, Math.Abs(XTypes.First().Key));
                            R = Formula.CalcRoot(R, Math.Abs(XTypes.First().Key));
                        }
                        else
                        {
                            L = L ^ Math.Abs(XTypes.First().Key);
                            R = R ^ Math.Abs(XTypes.First().Key);
                        }

                        return(await SolveAboutX(L, R, target));
                    }
                    else if (XTypes.Keys.First() <= -3)//3√以上かつ2つ
                    {
                        throw new Exception(AppResources.TooComplicatedX);
                    }
                    else//2√かつ2つ
                    {
                        L = L ^ 2;
                        R = R ^ 2;

                        return(await SolveAboutX(L, R, target));
                    }
                }
            }
            else if (!XTypes.Any(x => x.Key < 0))//ルートがない場合
            {
                var LXMin = XTypes.Keys.Min();
                if (IsRightZero)
                {
                    if (XTypes.Count() == 3)
                    {
                        var factoredx = XTypes.Keys.Select(x => x - LXMin).ToList();
                        var max       = factoredx.Max();
                        factoredx.Remove(0);
                        var min = factoredx.Min();

                        if (max == min * 2)
                        {
                            var ordered = L.NumMonof.GroupBy(x => x.Character[target])
                                          .ToDictionary(
                                x => x.Key,
                                x => new Formula(x.Select(y =>
                            {
                                var z = y;
                                z.Character.Remove(target);
                                return(z);
                            }).ToList()));

                            return((await SolveEquations.SolveEquation(ordered[max + LXMin], ordered[min + LXMin], ordered[LXMin]))
                                   .Concat(new List <Formula> {
                                (Formula)0
                            }).ToList());
                        }
                        else
                        {
                            throw new Exception(AppResources.TooComplicatedX);
                        }
                    }
                    else
                    {
                        var factoredx = XTypes.Keys.Select(x => x - LXMin).ToList();
                        var max       = factoredx.Max();

                        var ordered = L.NumMonof.GroupBy(x => x.Character[target])
                                      .ToDictionary(
                            x => x.Key,
                            x => new Formula(x.Select(y =>
                        {
                            var z = y;
                            z.Character.Remove(target);
                            return(z);
                        })
                                             .ToList()));

                        return(new List <Formula>
                        {
                            (Formula)0,
                            Formula.CalcRoot((Formula)(-1) * ordered[LXMin] / ordered[max + LXMin], max)
                        });
                    }
                }
                else
                {
                    if (XTypes.Keys.Max() == LXMin * 2)
                    {
                        var ordered = L.NumMonof.GroupBy(x => x.Character[target])
                                      .ToDictionary(
                            x => x.Key,
                            x => new Formula(x.Select(y =>
                        {
                            var z = y;
                            z.Character.Remove(target);
                            return(z);
                        }).ToList()));

                        return((await SolveEquations.SolveEquation(ordered[XTypes.Keys.Max()], ordered[LXMin], -R)).ToList());
                    }
                    else
                    {
                        throw new Exception(AppResources.TooComplicatedX);
                    }
                }
            }
            else if (XTypes.Count(x => x.Key < 0) == 1 && XTypes.Keys.Min() == -2)
            {
                var RootX = new Formula(XTypes[-2]);
                R = R - L + RootX;

                return(await SolveAboutX(RootX ^ 2, R ^ 2, target));
            }
            else if (XTypes.Count(x => x.Key < 0) == 1 && XTypes.Where(x => x.Key < 0).First().Value.Count() == 1)
            {
                var RootX = new Formula(XTypes[XTypes.Keys.Min()]);

                R = R - L + RootX;

                return(await SolveAboutX(RootX ^ XTypes.Keys.Min(), R ^ XTypes.Keys.Min(), target));
            }
            else if (XTypes.Count(x => x.Key < 0) == 2 && !XTypes.Any(x => x.Key > 0) && XTypes.Keys.Max() * 2 == XTypes.Keys.Min())
            {
                var max = XTypes.Keys.Max();
                var min = XTypes.Keys.Min();

                var MaxXs = XTypes[max].Select(x => x.GetTargetCharInfo(target) ^ max);
                var MinXs = XTypes[min].Select(x => x.GetTargetCharInfo(target) ^ min);

                if (MaxXs.Concat(MinXs).Distinct().Count() == 1)
                {
                    var formX = MaxXs.First();

                    var MaxExceptX = XTypes[max].Select(x => x.RemoveX(target)).ToList();
                    var MinExceptX = XTypes[min].Select(x => x.RemoveX(target)).ToList();

                    return(await SolveAboutX((Formula)formX, (await SolveEquations.SolveEquation(new Formula(MaxExceptX), new Formula(MinExceptX), R))[0], target));
                }
                else
                {
                    throw new Exception(AppResources.TooComplicatedX);
                }
            }
            else
            {
                throw new Exception(AppResources.TooComplicatedX);
            }
        }
    }