Пример #1
0
        /// <summary>
        /// LaTeX的な数式を普通の数式に変換
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string LaTeXtoFormula(string s)
        {
            if (s.Contains("{"))
            {
                for (int i = 0; i < s.Length; i++)
                {
                    if (s[i] == '~')
                    {
                        var LaTeXFuncName = Regex.Replace(s.Substring(i), "^~(\\w+)\\{.*$", "$1");

                        switch (LaTeXFuncName)
                        {
                        case "frac":
                            var Numor = OperateBrackets.TakeoutInsideofBracket(s.Substring(i + LaTeXFuncName.Length + 1), 0, "{}");
                            var Denor = OperateBrackets.TakeoutInsideofBracket(s.Substring(i + LaTeXFuncName.Length + 1 + Numor.Length + 2), 0, "{}");

                            s = s.Remove(i, 9 + Numor.Length + Denor.Length);
                            s = s.Insert(i, "(" + LaTeXtoFormula(Numor) + ")/(" + LaTeXtoFormula(Denor) + ")");
                            break;

                        case "root":
                            var rootindx = OperateBrackets.TakeoutInsideofBracket(s.Substring(i + LaTeXFuncName.Length + 1), 0, "{}");
                            var radicant = OperateBrackets.TakeoutInsideofBracket(s.Substring(i + LaTeXFuncName.Length + 1 + rootindx.Length + 2), 0, "{}");

                            s = s.Remove(i, 9 + rootindx.Length + radicant.Length);
                            s = s.Insert(i, "#$root$#(" + LaTeXtoFormula(rootindx) + "," + LaTeXtoFormula(radicant) + ")");
                            break;

                        default:
                            var parameters     = new List <string>();
                            var searchingindex = 0;

                            while (true)
                            {
                                var inside = OperateBrackets.TakeoutInsideofBracket(s.Substring(LaTeXFuncName.Length + 1 + i), searchingindex, "{}");
                                parameters.Add(inside);
                                searchingindex += inside.Length + 2;

                                if (s.Length <= searchingindex + LaTeXFuncName.Length + 1 ||
                                    (s.Length > searchingindex + LaTeXFuncName.Length + 1 && s[searchingindex + LaTeXFuncName.Length + 1] != '{'))
                                {
                                    break;
                                }
                            }

                            s = s.Remove(i, LaTeXFuncName.Length + 1 + searchingindex);
                            s = s.Insert(i, "#$" + LaTeXFuncName + "$#(" + string.Join(",", parameters) + ")");
                            break;
                        }
                    }
                    else if (s[i] == '^' && i + 1 < s.Length && s[i + 1] == '{')
                    {
                        var content = OperateBrackets.TakeoutInsideofBracket(s.Substring(i + 1), 0, "{}");

                        s = s.Remove(i, 3 + content.Length);
                        s = s.Insert(i, "^(" + LaTeXtoFormula(content) + ")");
                    }
                }
            }
            return(s);
        }
Пример #2
0
        /// <summary>
        /// LaTex的な数式でBackSpaceしたいときの関数
        /// </summary>
        /// <param name="NowFormula">LaTeX的な関数</param>
        /// <param name="locate">キャレットの位置</param>
        /// <returns>(BackSpace後の数式,BackSpace後のキャレットの位置)</returns>
        public static (string, int) BackSpace_LaTeX(string NowFormula, int locate)
        {
            int truelocate = CalcTrueLocate(NowFormula, locate);

            string past = "";

            if (truelocate > 0)
            {
                past = NowFormula[truelocate - 1].ToString();
            }

            //関数を消そうと画策してきたときの処理
            if (past == "{")
            {
                var bracketlocations = new List <(int, int)> {
                };

                var currentlocate = OperateBrackets.LocationofInsideofBracket(NowFormula, truelocate, "{}");
                bracketlocations.Add(currentlocate);

                var inspectionlocate = truelocate - 2;
                var backcount        = 0;
                while (true)
                {
                    if (NowFormula[inspectionlocate] == '}')
                    {
                        var nowlocate = OperateBrackets.LocationofInsideofBracket(NowFormula, inspectionlocate, "{}");
                        bracketlocations.Insert(0, nowlocate);

                        inspectionlocate = nowlocate.Item1 - 1;

                        backcount++;
                    }
                    else if (NowFormula[inspectionlocate] == '^')
                    {
                        bracketlocations.Insert(0, (inspectionlocate, inspectionlocate));

                        break;
                    }
                    else
                    {
                        bracketlocations.Insert(
                            0,
                            OperateBrackets.LocationofInsideofBracket(
                                NowFormula,
                                inspectionlocate,
                                "~" + NowFormula[inspectionlocate]
                                )
                            );

                        break;
                    }
                }

                inspectionlocate = currentlocate.Item2 + 1;

                while (true)
                {
                    if (inspectionlocate >= NowFormula.Length)
                    {
                        break;
                    }

                    if (NowFormula[inspectionlocate] == '{')
                    {
                        var nowlocate = OperateBrackets.LocationofInsideofBracket(NowFormula, inspectionlocate, "{}");
                        bracketlocations.Add(nowlocate);

                        inspectionlocate = nowlocate.Item2 + 1;
                    }
                    else
                    {
                        break;
                    }
                }

                var gap = bracketlocations[0].Item2 - bracketlocations[0].Item1 + 1;

                NowFormula = NowFormula.Remove(bracketlocations[0].Item1, gap);

                for (int i = 1; i < bracketlocations.Count(); i++)
                {
                    NowFormula = NowFormula.Remove(bracketlocations[i].Item1 - gap, 1);
                    gap++;
                    NowFormula = NowFormula.Remove(bracketlocations[i].Item2 - gap, 1);
                    gap++;
                }

                return(NowFormula, locate - backcount - 1);
            }
            else if (past == "}")
            {
                return(NowFormula, locate - 1);
            }
            else
            {
                var res = BackSpace(NowFormula.Substring(0, truelocate), locate);
                return(res.Item1 + NowFormula.Substring(truelocate), res.Item2);
            }
        }
Пример #3
0
        /// <summary>
        /// 数字のみの数式を計算する
        /// </summary>
        /// <param name="f">計算式</param>
        /// <returns>計算結果</returns>
        public static async Task <double> SolveNumFormula(string f)
        {
            f = LaTeXtoFormula(f);

            //monos:単項式ごとに分けられたもの
            var monos = OperateBrackets.FindMonomials(f).ToList();

            monos.Remove("");

            var resmonos = new double[0];

            resmonos = await monos.Select(async (mono) =>
            {
                if (double.TryParse(mono, out double num))//単項式が数字だけなら先に返してしまう
                {
                    return(num);
                }
                else
                {
                    //括弧に隣接する加減算記号を数字として扱う
                    mono = Regex.Replace(mono, "(\\+|\\-)\\(", "${1}1(");
                    mono = Regex.Replace(mono, "(\\+|\\-)\\#", "${1}1*#");

                    var bmap = OperateBrackets.MapingBrackets(mono);

                    //括弧が足りない場合は補完
                    if (bmap.Last() - bmap.First() > 0)
                    {
                        mono += new string(')', bmap.Last() - bmap.First());
                        bmap  = bmap.ToList().Concat(Enumerable.Range(0, bmap.Last() - bmap.First()).Reverse()).ToArray();
                    }

                    //括弧が正常な時の処理
                    if (bmap.First() == bmap.Last())
                    {
                        //演算子で区切る(累乗以外)、括弧はそのまま残す
                        var splitted = OperateBrackets.SplitByOperators(mono);

                        //累乗を計算する
                        while (splitted.Any(x => x.First() == '^'))
                        {
                            var n     = splitted.LastOrDefault(x => x.First() == '^');
                            int index = splitted.LastIndexOf(n);
                            if (index > 0)
                            {
                                string pastn = splitted[index - 1];

                                double pastfigure = 1;
                                double nowfigure  = 1;
                                char opera        = '*';

                                if (pastn.First() == '*' ||
                                    pastn.First() == '/' ||
                                    pastn.First() == '^')
                                {
                                    opera = pastn.First();

                                    if (!double.TryParse(pastn.Substring(1), out pastfigure))
                                    {
                                        pastfigure = await SolveNumFormula(pastn.Substring(2, pastn.Length - 3));
                                    }

                                    if (!double.TryParse(n.Substring(1), out nowfigure))
                                    {
                                        nowfigure = await SolveNumFormula(n.Substring(2, n.Length - 3));
                                    }
                                }
                                else
                                {
                                    if (!double.TryParse(pastn, out pastfigure))
                                    {
                                        pastfigure = await SolveNumFormula(pastn.Substring(1, pastn.Length - 2));
                                    }

                                    if (!double.TryParse(n.Substring(1), out nowfigure))
                                    {
                                        nowfigure = await SolveNumFormula(n.Substring(2, n.Length - 3));
                                    }
                                }

                                splitted.RemoveAt(index);
                                splitted.RemoveAt(index - 1);
                                splitted.Insert(index - 1, opera + Math.Pow(pastfigure, nowfigure).ToString());
                            }
                            else
                            {
                                throw new Exception("累乗でのエラー");
                            }
                        }

                        List <double> Numres = new List <double> {
                        };

                        //各項を処理する
                        foreach (string r in splitted)
                        {
                            string s = r;

                            //最初に"*"がついていたら消す
                            if (s.First() == '*')
                            {
                                s = s.Substring(1);
                            }

                            bool IsInverse = false;
                            if (s.First() == '/')
                            {
                                IsInverse = true;

                                //最初の"/"を消す
                                s = s.Substring(1);
                            }

                            if (s.First() == '#')//関数がある時
                            {
                                string funkname  = Regex.Replace(s, "^#\\$(([a-z|A-Z]|π)*)\\$#.*", "$1");
                                string inBracket = Regex.Replace(s, "^#\\$([a-z|A-Z]|π)*\\$#\\((.*)\\)$", "$2");

                                int[] inbracketmap = OperateBrackets.MapingBrackets(inBracket);

                                string CommaedinBracket = inBracket;
                                int lug = 0;
                                for (int i = 0; i < inBracket.Length; i++)
                                {
                                    if (inBracket[i] == ',' && inbracketmap[i] == 0)
                                    {
                                        CommaedinBracket = CommaedinBracket.Insert(i + lug++, ",");
                                    }
                                }

                                List <double> inBracketValues = (await CommaedinBracket.Split(new string[1] {
                                    ",,"
                                }, StringSplitOptions.None)
                                                                 .Select(async(x) => await SolveNumFormula(x))
                                                                 .WhenAll()).ToList();

                                if (IsInverse)
                                {
                                    Numres.Add(1 / await FuncItemService.RunFunc(inBracketValues, funkname));
                                }
                                else
                                {
                                    Numres.Add(await FuncItemService.RunFunc(inBracketValues, funkname));
                                }
                            }
                            else if (s.First() == '(')//括弧に囲まれたものの時
                            {
                                if (IsInverse)
                                {
                                    Numres.Add(1 / await SolveNumFormula(s.Substring(1, s.Length - 2)));
                                }
                                else
                                {
                                    Numres.Add(await SolveNumFormula(s.Substring(1, s.Length - 2)));
                                }
                            }
                            else//数字のみの時
                            {
                                if (IsInverse)
                                {
                                    Numres.Add(1 / double.Parse(s));
                                }
                                else
                                {
                                    Numres.Add(double.Parse(s));
                                }
                            }
                        }
                        return(Numres.Aggregate((now, next) => now *next));
                    }
                    else
                    {
                        throw new Exception(AppResources.BracketsWrong);
                    }
                }
            }).WhenAll();


            return(resmonos.Sum());
        }
Пример #4
0
        /// <summary>
        /// 数式の指定された部分に指定された文字を追加する
        /// </summary>
        /// <param name="nowformula"></param>
        /// <param name="figure"></param>
        /// <param name="locate"></param>
        /// <returns></returns>
        public async static Task <(string, int)> AddfigureManipulation(string nowformula, string figure, int locate)
        {
            string NowFormula = nowformula;

            //一つ前と二つ前の文字を抽出する
            //存在しなかった場合は""となる
            string PastChar     = "";
            string PastPastChar = "";

            try
            {
                PastChar     = NowFormula.Last().ToString();
                PastPastChar = NowFormula.Substring(NowFormula.Length - 2, 1);
            }
            catch { }

            if (figure == "/")//割り算が押された場合は分数を挿入する
            {
                if (NowFormula == "" || PastChar == "{" || PastChar == "(")
                {
                    NowFormula += "~frac{}{}";
                    locate++;
                }
                else
                {
                    int back = 0;
                    for (int i = NowFormula.Length - 1; i >= 0; i--)
                    {
                        if (Regex.IsMatch(NowFormula[i].ToString(), "^(\\+|\\-|\\*|/|\\(|\\{)$"))
                        {
                            back = i + 1;
                            break;
                        }
                        else if (NowFormula[i] == ')')
                        {
                            var locates = OperateBrackets.LocationofInsideofBracket(NowFormula, i);
                            i = locates.Item1;

                            if (i != 0 && NowFormula[i - 1] == '#')
                            {
                                for (int j = i - 2; j >= 0; j--)
                                {
                                    if (NowFormula[j] == '#')
                                    {
                                        i = j;
                                        break;
                                    }
                                }
                            }
                        }
                        else if (NowFormula[i] == '}')
                        {
                            var locates = OperateBrackets.LocationofInsideofBracket(NowFormula, i, "{}");
                            i = locates.Item1;
                        }
                    }

                    var Numor = NowFormula.Substring(back);
                    if (NowFormula != "" && NowFormula.Length > back)
                    {
                        NowFormula = NowFormula.Remove(back);
                    }


                    NowFormula = NowFormula + "~frac{" + Numor + "}{}";

                    locate += 2;
                }
            }
            else if (figure == "root")
            {
                NowFormula += "~root{2}{}";

                locate += 3;
            }
            else if (figure == "^")
            {
                if (!Regex.IsMatch(PastChar, "^(\\+|\\-|\\*|/|\\^|\\(|\\{)$"))
                {
                    NowFormula += "^{}";

                    locate += 1;
                }
            }
            else if (PastChar == "-" && //前が-
                     Regex.IsMatch(PastPastChar, "^(\\*|/|\\^|\\()$") &&//前の前が*,/,^,(
                     Regex.IsMatch(figure, "^(\\+|\\-|\\*|/|\\^|\\))$"))//今のが+,-,*,/,^,)
            {
                switch (figure)
                {
                case "+":
                    (NowFormula, locate) = BackSpace(NowFormula, locate);
                    break;

                case "-":
                    (NowFormula, locate) = BackSpace(NowFormula, locate);
                    NowFormula          += figure;
                    break;

                case "*":
                case "/":
                case "^":
                    (NowFormula, locate) = BackSpace(NowFormula, locate);
                    (NowFormula, locate) = BackSpace(NowFormula, locate);
                    NowFormula          += figure;
                    break;

                case ")":
                    (NowFormula, locate) = BackSpace(NowFormula, locate);
                    (NowFormula, locate) = BackSpace(NowFormula, locate);
                    break;

                default:
                    Trace.WriteLine("内部エラー");
                    break;
                }

                locate++;
            }
            else if (Regex.IsMatch(PastChar, "^(\\+|\\-)$") &&//前が+,-
                     Regex.IsMatch(figure, "^(\\+|\\-|\\*|/|\\^|\\))$"))//今のが+,-,*,/,^,)
            {
                (NowFormula, locate) = BackSpace(NowFormula, locate);
                NowFormula          += figure;

                locate++;
            }
            else if (Regex.IsMatch(PastChar, "^(\\*|/|\\^|\\()$") &&//前が*,/,^,(
                     Regex.IsMatch(figure, "^(\\+|\\*|/|\\^|\\))$"))//今のが+,*,/,^,)
            {
                (NowFormula, locate) = BackSpace(NowFormula, locate);
                NowFormula          += figure;

                locate++;
            }
            else if (figure == "invert" && !Regex.IsMatch(PastChar, "^(\\+|\\-|\\*|/|\\^|\\()$"))//逆数ボタンを押した時
            {
                NowFormula += "^{-1}";

                locate += 4;
            }
            else if (figure == "invert")
            {
            }
            else if (figure.First() == '~')
            {
                if (await FuncItemService.IsExist(figure.Substring(1)))
                {
                    var count = (await FuncItemService.GetByName(figure.Substring(1))).CharCount;

                    if (count == 0)
                    {
                        NowFormula += figure + "{}";
                        locate     += 1;
                    }
                    else
                    {
                        NowFormula += figure + (new StringBuilder()).Insert(0, "{}", count).ToString();
                    }
                }

                locate += 1;
            }
            else if (figure == "." && PastChar == ".")//小数点
            {
            }
            else
            {
                NowFormula += figure;

                locate++;
            }

            return(NowFormula, locate);
        }
Пример #5
0
        /// <summary>
        /// 括弧のある式を展開
        /// </summary>
        /// <param name="f">括弧のある式</param>
        /// <returns>括弧のない多項式</returns>
        private async static Task <Formula> Expand(string f)
        {
            //-{文字列}のときは -1{文字列}に直す
            f = Regex.Replace(f, "-([a-z|A-Z]|\\()", "-1$1");

            //単項式に分割
            var fs = OperateBrackets.FindMonomials(f).ToList();

            //単項式ごとに処理
            List <Formula> mf = (await fs.Select(async(m) =>
            {
                if (m.First() == '*')
                {
                    m.Substring(1);
                }

                if (Monomial.IsMonomial(m))
                {
                    return(new Formula(await Monomial.CreateByStr(m)));
                }
                else
                {
                    //括弧に隣接する加減算記号を数字として扱う
                    m = Regex.Replace(m, "(\\+|\\-)\\(", "${1}1(");

                    var bmap = OperateBrackets.MapingBrackets(m);

                    if (bmap.First() - bmap.Last() > 0)
                    {
                        throw new Exception(AppResources.BracketsWrong);
                    }

                    //括弧が足りない場合は補完
                    if (bmap.Last() - bmap.First() > 0)
                    {
                        m += new string(')', bmap.Last() - bmap.First());
                        bmap = bmap.ToList().Concat(
                            Enumerable.Range(0, bmap.Last() - bmap.First()).Reverse()
                            ).ToArray();
                    }

                    //中身のない括弧を消す
                    m = Regex.Replace(m, "\\(\\)", "");

                    if (m.Length == 0)
                    {
                        return((Formula)0);
                    }

                    //括弧が一致したとき
                    if (bmap.First() == bmap.Last())
                    {
                        //前に演算子がついていないときは乗算記号をつける
                        if (!Regex.IsMatch(m.First().ToString(), "^(\\*|/|\\^|\\()$"))
                        {
                            m = m.Insert(0, "*");
                        }

                        //累乗を処理
                        if (m.Contains("^"))
                        {
                            m = await ExpandPowAsync(m);
                        }

                        //扱いやすい単位まで分割
                        var splitteds = OperateBrackets.SplitByOperators(m);

                        var Numerator = new List <Formula> {
                        };
                        var Denominator = new List <Formula> {
                        };

                        foreach (string splitted in splitteds)
                        {
                            if (splitted.Length == 0)
                            {
                                continue;
                            }

                            var splt = splitted;

                            if (splt.First() == '*')
                            {
                                splt = splt.Substring(1);
                            }

                            var IsDenom = splt.First() == '/';
                            if (IsDenom)
                            {
                                splt = splt.Substring(1);
                            }

                            switch (splt.First())
                            {
                            case '(':
                                if (IsDenom)
                                {
                                    Denominator.Add(await Expand(splt.Substring(1, splt.Length - 2)));
                                }
                                else
                                {
                                    Numerator.Add(await Expand(splt.Substring(1, splt.Length - 2)));
                                }
                                break;

                            default:
                                if (IsDenom)
                                {
                                    Denominator.Add(await Expand(splt));
                                }
                                else
                                {
                                    Numerator.Add(await Expand(splt));
                                }
                                break;
                            }
                        }

                        if (Numerator.Count() == 0)
                        {
                            Numerator.Add((Formula)1);
                        }
                        if (Denominator.Count() == 0)
                        {
                            Denominator.Add((Formula)1);
                        }

                        return(Numerator.Aggregate((now, next) => now * next) / Denominator.Aggregate((now, next) => now * next));
                    }
                    else
                    {
                        throw new Exception(AppResources.BracketsDontMatch);
                    }
                }
            }).WhenAll()).ToList();

            return(mf.Aggregate((now, next) => now + next));
        }
Пример #6
0
        /// <summary>
        /// 文字式(未整理)の累乗を処理
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static async Task <string> ExpandPowAsync(string f)
        {
            if (f.Contains("^"))
            {
                f = Regex.Replace(f, "^\\^(\\+|-)?(\\d|\\.)*", ""); //頭の累乗記号+数字は消す
                f = Regex.Replace(f, "\\^$", "");                   //末尾の累乗記号も消す
                f = Regex.Replace(f, "\\^([a-z|A-Z])", "$1");       //文字で累乗されている場合は累乗をなかったことにする

                f = Regex.Replace(f, "[a-z|A-Z]\\^(\\d)+", Match =>
                {
                    return(new string(Match.Value.First(), int.Parse(Regex.Replace(Match.Value, "(.*)(\\d+)(.*)", "$2"))));
                });

                while (f.Contains("^"))
                {
                    int PowIndex = f.IndexOf('^');

                    if (PowIndex == 0)
                    {
                        throw new Exception(AppResources.PowerMustTop);
                    }

                    string Powed = "1";
                    if (f[PowIndex - 1] == ')')
                    {
                        //Xamarin.Forms.DependencyService.Get<IToastService>()
                        //.Show("括弧に'^'は付けられません");

                        Powed = "(" + OperateBrackets.TakeoutInsideofBracket(f, PowIndex - 2) + ")";

                        throw new Exception(AppResources.CantAddPowerAfterParenthes);
                    }
                    else if (Regex.IsMatch(f[PowIndex - 1].ToString(), "(\\+|-)?(\\d|\\.)"))
                    {
                        Powed = Regex.Match(f.Substring(0, PowIndex), "(\\+|-)?(\\d+|\\.)$").Value;
                    }
                    else
                    {
                        Powed = f[PowIndex - 1].ToString();
                    }

                    Double Powist = 1.0;
                    if (f[PowIndex + 1] == '(')
                    {
                        var content = OperateBrackets.TakeoutInsideofBracket(f, PowIndex + 1);

                        if (Regex.IsMatch(content, "[a-z]"))
                        {
                            throw new Exception(AppResources.CantAddPowerAfterChar);
                        }

                        Powist = await SolveNumFormulas.SolveNumFormula(content);

                        f = f.Remove(PowIndex - 1, content.Length + 4);//^の分(1)+カッコの分(2)+
                    }
                    else
                    {
                        var content = Regex.Match(f.Substring(PowIndex), "^(\\+|-)?(\\d|\\.)+").Value;

                        Powist = double.Parse(content);

                        f = f.Remove(PowIndex - 1, content.Length + 2);
                    }

                    var repeated = "";

                    if (double.TryParse(Powed, out double Poweddouble))
                    {
                        repeated = Math.Pow(Poweddouble, Powist).ToString();
                    }
                    else
                    {
                        repeated = string.Concat(Enumerable.Repeat(Powed, (int)Powist));
                    }

                    f = f.Insert(PowIndex - 1, repeated);
                }
            }

            return(f);
        }