コード例 #1
0
        /// <summary>
        /// 按位取模运算(不考虑正负号)
        /// </summary>
        /// <param name="num">模数</param>
        /// <param name="maxDecimalPlaces">答案保留小数位数</param>
        /// <returns>包含余数和商的元组</returns>
        protected override (Digitable, Digitable) Mod_unsigned(Digitable num, int maxDecimalPlaces)
        {
            NumStr a = this, b = num as NumStr;

            if (a == null || b == null)
            {
                throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue);
            }
            //统一计算空间
            if (a.Space != b.Space)
            {
                if (a.Space == OperationSpace.DefaultSpace)
                {
                    a = (NumStr)a.ChangeOperationSpace(b.Space);
                }
                else if (b.Space == OperationSpace.DefaultSpace)
                {
                    b = (NumStr)b.ChangeOperationSpace(a.Space);
                }
                else
                {
                    throw new ProgramInterruptException(ProgramInterruptExceptionType.NotSameOperationSpace);
                }
            }

            if (CompareAbsolute(a, b) < 0)
            {
                return(new NumStr(a), new NaturalNumStr(0, a.Space));
            }
            var quotient = a.Divide_unsigned(b, 0) as NumStr;
            var ans      = a.Minus_unsigned(quotient * b, maxDecimalPlaces, out bool tmp);

            return(ans, quotient);
        }
コード例 #2
0
ファイル: NumStrTest.cs プロジェクト: zamhown/NaturplayMath
        public void SqrtTest()
        {
            var a1 = Digitable.Sqrt(new NumStr("3"));

            Assert.AreEqual(a1.ToString(), "1.7320508075");
            a1 = Digitable.Sqrt(new NumStr("0.0001"));
            Assert.AreEqual(a1.ToString(), "0.01");
            a1 = Digitable.Sqrt(new NumStr("8569755963"));
            Assert.AreEqual(a1.ToString(), "92572.9764186071");
        }
コード例 #3
0
ファイル: NumStr.cs プロジェクト: zamhown/NaturplayMath
        /// <summary>
        /// 乘方运算(不考虑正负号)
        /// </summary>
        /// <param name="num">指数</param>
        /// <param name="maxDecimalPlaces">答案保留小数位数</param>
        /// <returns></returns>
        protected override Digitable Power_unsigned(Digitable num, int maxDecimalPlaces)
        {
            NumStr a = this, b = num as NumStr;

            if (a == null || b == null)
            {
                throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue);
            }
            //统一计算空间
            if (a.Space != b.Space)
            {
                if (a.Space == OperationSpace.DefaultSpace)
                {
                    a = (NumStr)a.ChangeOperationSpace(b.Space);
                }
                else if (b.Space == OperationSpace.DefaultSpace)
                {
                    b = (NumStr)b.ChangeOperationSpace(a.Space);
                }
                else
                {
                    throw new ProgramInterruptException(ProgramInterruptExceptionType.NotSameOperationSpace);
                }
            }
            //特殊情况
            if (a.IsZero)
            {
                if (b.IsZero)
                {
                    throw new IllegalOperationException(IllegalOperationExceptionType.ZeroSquareOfZero);
                }
                return(new NumStr(0, a.Space, maxDecimalPlaces));
            }
            else if (b.IsZero)
            {
                return(new NumStr(1, a.Space, maxDecimalPlaces));
            }

            NumStr ans;
            //将指数分割出整数,先做快速幂
            var split = b.SplitByDecimalPoint();

            if (!split.Item1.IsZero)
            {
                if (split.Item1.IsOne)
                {
                    ans = split.Item2.IsZero ? new NumStr(a, maxDecimalPlaces) : a;
                }
                else
                {
                    var tmp = a;
                    ans = new NumStr(1, a.Space, maxDecimalPlaces);
                    //将指数化为2进制
                    var binary = split.Item1.ChangeOperationSpace(new OperationSpace(0, 2)) as NumStr;
                    var count  = 0;
                    foreach (var i in binary.integerNumList)
                    {
                        if (i == 1)
                        {
                            ans = ans.Multiply_unsigned(tmp, maxDecimalPlaces) as NumStr;
                            ans.PositiveOrNegative = 1;  //小心符号陷阱
                        }
                        if (++count < binary.integerNumList.Count)
                        {
                            tmp = tmp.Multiply_unsigned(tmp, maxDecimalPlaces) as NumStr;
                            tmp.PositiveOrNegative = 1;  //小心符号陷阱
                        }
                    }
                }
            }
            else
            {
                ans = new NumStr(1, a.Space, maxDecimalPlaces);
            }

            //小数部分乘方

            return(ans);
        }
コード例 #4
0
 /// <summary>
 /// 整除运算符
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 /// <returns></returns>
 public static NaturalNumStr operator /(NaturalNumStr a, NaturalNumStr b) => new NaturalNumStr(Digitable.Divide(a, b, 0) as NumStr, false);
コード例 #5
0
ファイル: NumStr.cs プロジェクト: zamhown/NaturplayMath
        /// <summary>
        /// 按位乘法运算(不考虑正负号)
        /// </summary>
        /// <param name="num">乘数</param>
        /// <param name="maxDecimalPlaces">答案保留小数位数</param>
        /// <returns></returns>
        protected override Digitable Multiply_unsigned(Digitable num, int maxDecimalPlaces)
        {
            NumStr a = this, b = num as NumStr;

            if (a == null || b == null)
            {
                throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue);
            }
            //统一计算空间
            if (a.Space != b.Space)
            {
                if (a.Space == OperationSpace.DefaultSpace)
                {
                    a = (NumStr)a.ChangeOperationSpace(b.Space);
                }
                else if (b.Space == OperationSpace.DefaultSpace)
                {
                    b = (NumStr)b.ChangeOperationSpace(a.Space);
                }
                else
                {
                    throw new ProgramInterruptException(ProgramInterruptExceptionType.NotSameOperationSpace);
                }
            }
            var ans = new NumStr(0, a.Space, maxDecimalPlaces);

            //特殊情况
            if (a.IsZero || b.IsZero)
            {
                return(ans);
            }

            var ansDecimalPlaces = a.DecimalPlaces + b.DecimalPlaces;

            //更换乘数
            if (a.integerNumList == null && a.decimalNumList?.First.Value == 0)
            {
                a = a.RemoveDecimalPoint();
            }
            if (b.integerNumList == null && b.decimalNumList?.First.Value == 0)
            {
                b = b.RemoveDecimalPoint();
            }

            long remain       = 0;
            var  maxAnsPlaces = DefaultSettings.MaxIntegerPlaces + ansDecimalPlaces;
            var  tmpList      = new LinkedList <uint>(); //缓存链
            var  ptrHead      = tmpList.First;
            var  ptr          = tmpList.First;

            foreach (var bi in b)
            {
                if (ptrHead == null)
                {
                    tmpList.AddLast(0);
                    if (tmpList.Count > maxAnsPlaces)
                    {
                        throw new NumberOutOfRangeException();
                    }
                    ptrHead = tmpList.Last;
                }
                ptr = ptrHead;
                if (bi > 0)
                {
                    foreach (var ai in a)
                    {
                        var product = ai * bi + remain;
                        remain   = product / ans.NumberBase;
                        product %= ans.NumberBase;
                        if (ptr == null)
                        {
                            tmpList.AddLast((uint)product);
                            if (tmpList.Count > maxAnsPlaces)
                            {
                                throw new NumberOutOfRangeException();
                            }
                            ptr = tmpList.Last;
                        }
                        else
                        {
                            ptr.Value += (uint)product;
                        }
                        ptr = ptr.Next;
                    }
                    if (remain > 0)
                    {
                        if (ptr == null)
                        {
                            tmpList.AddLast((uint)remain);
                            if (tmpList.Count > maxAnsPlaces)
                            {
                                throw new NumberOutOfRangeException();
                            }
                        }
                        else
                        {
                            ptr.Value += (uint)remain;
                        }
                        remain = 0;
                    }
                }
                ptrHead = ptrHead.Next;
            }
            //依次进位
            remain = 0;
            ptr    = tmpList.First;
            while (ptr != null)
            {
                ptr.Value += (uint)remain;
                if (ptr.Value >= ans.NumberBase)
                {
                    remain     = ptr.Value / ans.NumberBase;
                    ptr.Value %= ans.NumberBase;
                }
                else
                {
                    remain = 0;
                }
                ptr = ptr.Next;
            }
            if (remain > 0)
            {
                tmpList.AddLast((uint)remain);
                if (tmpList.Count > maxAnsPlaces)
                {
                    throw new NumberOutOfRangeException();
                }
            }
            //录入答案
            ptr = tmpList.First;
            //调整光标位置
            var tmpn = Math.Max(0, (long)ansDecimalPlaces - (long)maxDecimalPlaces);

            for (int i = 0; i < tmpn; i++)
            {
                ptr = ptr.Next;
            }
            var  DecimalPlaces = Math.Min(ansDecimalPlaces, maxDecimalPlaces);
            bool flag          = true; //判断小数位最高位是否为0

            for (int i = 0; i < DecimalPlaces; i++)
            {
                if (ptr == null)
                {
                    ans.decimalNumList.AddFirst(0);
                }
                else
                {
                    if (ptr.Value > 0 || !flag)
                    {
                        if (flag)
                        {
                            flag = false;
                            ans.decimalNumList = new LinkedList <uint>();
                        }
                        ans.decimalNumList.AddFirst(ptr.Value);
                    }
                    ptr = ptr.Next;
                }
            }
            if (ptr != null)
            {
                ans.integerNumList = new LinkedList <uint>();
                do
                {
                    ans.integerNumList.AddLast(ptr.Value);
                    ptr = ptr.Next;
                }while (ptr != null);
            }
            return(ans);
        }
コード例 #6
0
 public int Compare(Digitable a, Digitable b)
 {
     // todo:比较任意两个数字的大小
     throw new System.Exception();
 }
コード例 #7
0
        /// <summary>
        /// 将本数和另一个数取绝对值进行比较,大于输出1,小于输出-1,等于输出0
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public override int CompareAbsolute(Digitable num)
        {
            NumStr a = this, b = num as NumStr;

            if (ReferenceEquals(a, b))
            {
                return(0);
            }

            if (a == null || b == null)
            {
                throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue);
            }
            //统一计算空间
            if (a.Space != b.Space)
            {
                if (a.Space == OperationSpace.DefaultSpace)
                {
                    a = (NumStr)a.ChangeOperationSpace(b.Space);
                }
                else if (b.Space == OperationSpace.DefaultSpace)
                {
                    b = (NumStr)b.ChangeOperationSpace(a.Space);
                }
                else
                {
                    throw new ProgramInterruptException(ProgramInterruptExceptionType.NotSameOperationSpace);
                }
            }

            if (a.IntegerPlaces > b.IntegerPlaces)
            {
                return(1);
            }
            else if (a.IntegerPlaces < b.IntegerPlaces)
            {
                return(-1);
            }
            else
            {
                //比较整数
                if (a.integerNumList != null)
                {
                    var ai = a.integerNumList.Last;
                    var bi = b.integerNumList.Last;
                    while (ai != null && ai.Value == bi.Value)
                    {
                        ai = ai.Previous;
                        bi = bi.Previous;
                    }
                    if (ai != null)
                    {
                        return(ai.Value > bi.Value ? 1 : -1);
                    }
                }
                //比较小数
                if (a.decimalNumList != null && b.decimalNumList == null)
                {
                    return(1);
                }
                else if (a.decimalNumList == null && b.decimalNumList != null)
                {
                    return(-1);
                }
                else if (a.decimalNumList == null && b.decimalNumList == null)
                {
                    return(0);
                }
                else
                {
                    var ai = a.decimalNumList.First;
                    var bi = b.decimalNumList.First;
                    while (ai != null && bi != null && ai.Value == bi.Value)
                    {
                        ai = ai.Next;
                        bi = bi.Next;
                    }
                    if (ai != null && bi == null)
                    {
                        return(1);
                    }
                    else if (ai == null && bi != null)
                    {
                        return(-1);
                    }
                    else if (ai == null && bi == null)
                    {
                        return(0);
                    }
                    else
                    {
                        return(ai.Value > bi.Value ? 1 : -1);
                    }
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// 取模运算
        /// </summary>
        /// <param name="a">被模数</param>
        /// <param name="b">模数</param>
        /// <param name="maxDecimalPlaces">答案保留小数位数</param>
        /// <returns>包含余数和商的元组</returns>
        public static (NumStr, NumStr) Mod(NumStr a, NumStr b, int maxDecimalPlaces)
        {
            var ans = Digitable.Mod(a, b, maxDecimalPlaces);

            return(ans.Item1 as NumStr, ans.Item2 as NumStr);
        }
コード例 #9
0
ファイル: NumStr.cs プロジェクト: zamhown/NaturplayMath
        /// <summary>
        /// 按位除法运算(不考虑正负号)
        /// </summary>
        /// <param name="num">除数</param>
        /// <param name="maxDecimalPlaces">答案保留小数位数</param>
        /// <returns></returns>
        protected override Digitable Divide_unsigned(Digitable num, int maxDecimalPlaces)
        {
            NumStr a = this, b = num as NumStr;

            //方法:手动模拟法 + 二分查找优化
            if (a == null || b == null)
            {
                throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue);
            }
            //统一计算空间
            if (a.Space != b.Space)
            {
                if (a.Space == OperationSpace.DefaultSpace)
                {
                    a = (NumStr)a.ChangeOperationSpace(b.Space);
                }
                else if (b.Space == OperationSpace.DefaultSpace)
                {
                    b = (NumStr)b.ChangeOperationSpace(a.Space);
                }
                else
                {
                    throw new ProgramInterruptException(ProgramInterruptExceptionType.NotSameOperationSpace);
                }
            }
            var ans = new NumStr(0, a.Space, maxDecimalPlaces);

            //特殊情况
            if (a.IsZero)
            {
                return(ans);
            }
            else if (b.IsZero)
            {
                throw new IllegalOperationException(IllegalOperationExceptionType.DivideByZero);
            }

            int a_ptr           = 0;
            var a_integerPlaces = a.IntegerPlaces + b.DecimalPlaces;  //被除数的小数点位置

            if (b.decimalNumList != null)
            {
                b = b.RemoveDecimalPoint();
            }
            var an = a.IntegerPlaces + a.DecimalPlaces;
            var bn = b.IntegerPlaces;

            var  new_a                     = new NumStr(0, a.Space, 0);  //被除数片段
            var  b_table                   = new NumStr[ans.NumberBase]; //除数的倍数表
            var  aii                       = a.GetInverseEnumerator();
            var  bii                       = b.GetInverseEnumerator();
            bool?a_less_than_b             = null;
            LinkedListNode <uint> node_ptr = null;

            while (true)
            {
                //补位
                bii           = b.GetInverseEnumerator();
                a_less_than_b = null;
                if (new_a.IsPositive)
                {
                    var aii2 = new_a.GetInverseEnumerator();
                    while (a_less_than_b == null && aii2.MoveNext() && bii.MoveNext())
                    {
                        if (aii2.Current < bii.Current)
                        {
                            a_less_than_b = true;
                        }
                        else if (aii2.Current > bii.Current)
                        {
                            a_less_than_b = false;
                        }
                    }
                }
                do
                {
                    var v = aii.MoveNext() ? aii.Current : 0;
                    if (v > 0 || new_a.IsPositive)
                    {
                        if (new_a.IsZero)
                        {
                            new_a.PositiveOrNegative = 1;
                            new_a.integerNumList     = new LinkedList <uint>();
                        }
                        new_a.integerNumList.AddFirst(v);
                        bii.MoveNext();
                        if (a_less_than_b == null)
                        {
                            if (v < bii.Current)
                            {
                                a_less_than_b = true;
                            }
                            else if (v > bii.Current)
                            {
                                a_less_than_b = false;
                            }
                        }
                    }
                    a_ptr++;
                    if (a_ptr <= a_integerPlaces)
                    {
                        if (ans.IsZero)
                        {
                            ans.PositiveOrNegative = 1;
                            ans.integerNumList     = new LinkedList <uint>();
                        }
                        if (ans.IntegerPlaces != 1 || ans.integerNumList.Last.Value > 0)
                        {
                            ans.integerNumList.AddFirst(0);
                            if (ans.IntegerPlaces > DefaultSettings.MaxIntegerPlaces)
                            {
                                throw new NumberOutOfRangeException();
                            }
                            node_ptr = ans.integerNumList.First;
                        }
                    }
                    else
                    {
                        if (ans.DecimalPlaces == maxDecimalPlaces)
                        {
                            return(ans);
                        }
                        if (ans.decimalNumList == null)
                        {
                            ans.decimalNumList = new LinkedList <uint>();
                        }
                        ans.decimalNumList.AddLast(0);
                        node_ptr = ans.decimalNumList.Last;
                    }
                } while (new_a.IntegerPlaces < bn + (a_less_than_b == true ? 1 : 0));
                //做整除
                var quotient = Divide_unsigned_b_table_binary_search(b_table, b, new_a);
                if (node_ptr != null)
                {
                    node_ptr.Value = quotient;
                    node_ptr       = null;
                }
                else
                {
                    if (a_ptr <= a_integerPlaces)
                    {
                        if (ans.integerNumList == null)
                        {
                            ans.integerNumList = new LinkedList <uint>();
                        }
                        ans.integerNumList.AddFirst(quotient);
                        if (ans.IntegerPlaces > DefaultSettings.MaxIntegerPlaces)
                        {
                            throw new NumberOutOfRangeException();
                        }
                    }
                    else
                    {
                        if (ans.decimalNumList == null)
                        {
                            ans.decimalNumList = new LinkedList <uint>();
                        }
                        ans.decimalNumList.AddLast(quotient);
                    }
                }
                if (maxDecimalPlaces > 0 && ans.DecimalPlaces >= maxDecimalPlaces)
                {
                    return(ans);
                }
                //求余
                new_a = new_a - b_table[quotient];
                if (new_a.IsZero && a_ptr >= an)
                {
                    return(ans);
                }
            }
        }