Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
                }
            }
        }