Beispiel #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);
        }
Beispiel #2
0
        /// <summary>
        /// 改变元素的计算空间
        /// </summary>
        /// <param name="space">新的计算空间,为null即为默认计算空间</param>
        /// <param name="newInstance">是否返回新的实例(如果为null,即为不确定)</param>
        /// <param name="maxDecimalPlaces">最大保留小数位数</param>
        /// <returns></returns>
        protected NumStr ChangeOS(OperationSpace space, bool?newInstance, int?maxDecimalPlaces)
        {
            if (space == null)
            {
                space = OperationSpace.DefaultSpace;
            }
            if (this.Space == space && (maxDecimalPlaces == null || maxDecimalPlaces == space.DefaultMaxDecimalPlaces))
            {
                if (newInstance == true)
                {
                    return(new NumStr(this));
                }
                else
                {
                    return(this);
                }
            }
            NumStr new_num = new NumStr(0, space, maxDecimalPlaces);

            if (IsZero)
            {
                return(new_num);
            }
            new_num.PositiveOrNegative = PositiveOrNegative;
            NumberBaseConversion(new_num, space.NumberBase, this);
            if (newInstance == false)
            {
                Copy(new_num, null, false);
                return(this);
            }
            else
            {
                return(new_num);
            }
        }
Beispiel #3
0
        /// <summary>
        /// 取自然对数
        /// </summary>
        /// <param name="maxDecimalPlaces">答案保留小数位数</param>
        /// <returns></returns>
        protected override Digitable Ln(int maxDecimalPlaces)
        {
            NumStr a = this;

            if (a == null)
            {
                throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue);
            }
            //特殊情况
            if (!a.IsPositive)
            {
                throw new IllegalOperationException(IllegalOperationExceptionType.AntilogIsNotPositive);
            }
            else if (a.IsOne)
            {
                return(new NumStr(0, a.Space, maxDecimalPlaces));
            }

            /* 原理:
             * 泰勒展开式:ln(1+x) = x-x^2/2+x^3/3-...+(-1)^(k-1)*(x^k)/k
             * = x(1-x(1/2-x(1/3-x(1/4-x(1/5...)))))
             */
            NumStr ans = null;

            return(ans);
        }
Beispiel #4
0
 /// <summary>
 /// 拷贝初始化
 /// </summary>
 /// <param name="num">原始对象</param>
 /// <param name="deep">是否为深拷贝</param>
 public NaturalNumStr(NumStr num, bool deep = true)
     : base(num, 0, deep)
 {
     if (PositiveOrNegative < 0)
     {
         PositiveOrNegative = 1;
     }
 }
Beispiel #5
0
 /// <summary>
 /// 用纯数字初始化,转换为指定的计算空间
 /// </summary>
 /// <param name="num">数字</param>
 /// <param name="space">计算空间</param>
 public NaturalNumStr(NumStr num, OperationSpace space)
     : base(num, space, 0)
 {
     if (PositiveOrNegative < 0)
     {
         PositiveOrNegative = 1;
     }
 }
Beispiel #6
0
 /// <summary>
 /// 用相同类型的数字初始化,转换为指定的计算空间
 /// </summary>
 /// <param name="num">原始对象</param>
 /// <param name="space">计算空间</param>
 /// <param name="maxDecimalPlaces">最大保留小数位数</param>
 /// <param name="positiveOrNegative">正负性</param>
 public NumStr(NumStr num, OperationSpace space, int?maxDecimalPlaces = null, int?positiveOrNegative = null)
 {
     Space = space ?? num.Space;
     PositiveOrNegative = positiveOrNegative ?? num.PositiveOrNegative;
     MaxDecimalPlaces   = maxDecimalPlaces.HasValue ?
                          Math.Min(maxDecimalPlaces.Value, this.Space.DefaultMaxDecimalPlaces)
         : this.Space.DefaultMaxDecimalPlaces;
     NumberBaseConversion(this, Space.NumberBase, num);
 }
Beispiel #7
0
 /// <summary>
 /// 拷贝
 /// </summary>
 /// <param name="num">原始对象</param>
 /// <param name="maxDecimalPlaces">最大保留小数位数</param>
 /// <param name="deep">是否为深拷贝</param>
 protected void Copy(NumStr num, int?maxDecimalPlaces = null, bool deep = true)
 {
     PositiveOrNegative = num.PositiveOrNegative;
     Space            = num.Space;
     MaxDecimalPlaces = maxDecimalPlaces.HasValue ? Math.Min(maxDecimalPlaces.Value, this.Space.DefaultMaxDecimalPlaces) : num.MaxDecimalPlaces;
     integerNumList   = null;
     decimalNumList   = null;
     if (deep)
     {
         if (num.integerNumList != null)
         {
             integerNumList = new LinkedList <uint>();
             foreach (var i in num.integerNumList)
             {
                 integerNumList.AddLast(i);
             }
         }
         if (MaxDecimalPlaces > 0 && num.decimalNumList != null)
         {
             decimalNumList = new LinkedList <uint>();
             var i = num.decimalNumList.First;
             while (i != null && DecimalPlaces < MaxDecimalPlaces)
             {
                 decimalNumList.AddLast(i.Value);
                 i = i.Next;
             }
         }
     }
     else
     {
         integerNumList = num.integerNumList;
         if (MaxDecimalPlaces < num.DecimalPlaces)
         {
             decimalNumList = new LinkedList <uint>();
             var i = num.decimalNumList.First;
             while (i != null && DecimalPlaces < MaxDecimalPlaces)
             {
                 decimalNumList.AddLast(i.Value);
                 i = i.Next;
             }
         }
         else
         {
             decimalNumList = num.decimalNumList;
         }
     }
 }
Beispiel #8
0
 public InverseEnumerator(NumStr num)
 {
     list    = num;
     current = 0;
     if (list.integerNumList != null)
     {
         node = list.integerNumList.Last;
     }
     else if (list.decimalNumList != null)
     {
         node = list.decimalNumList.First;
     }
     else
     {
         node = null;
     }
 }
Beispiel #9
0
        /// <summary>
        /// 从小数点处分割,分别生成整数与小数部分
        /// </summary>
        /// <param name="deepCopy">分割时是否深拷贝</param>
        /// <returns>包含整数与小数的元组</returns>
        public (NumStr, NumStr) SplitByDecimalPoint(bool deepCopy = false)
        {
            var integerPart = new NumStr(this, 0, deepCopy);
            var decimalPart = new NumStr(0, Space, MaxDecimalPlaces);

            if (decimalNumList != null)
            {
                decimalPart.PositiveOrNegative = PositiveOrNegative;
                if (deepCopy)
                {
                    decimalPart.decimalNumList = new LinkedList <uint>();
                    foreach (var i in decimalNumList)
                    {
                        decimalPart.decimalNumList.AddLast(i);
                    }
                }
                else
                {
                    decimalPart.decimalNumList = decimalNumList;
                }
            }
            return(integerPart, decimalPart);
        }
Beispiel #10
0
        /// <summary>
        /// 按位除法运算的除数倍数表的二分查找
        /// </summary>
        /// <param name="b_table">数组</param>
        /// <param name="b">除数</param>
        /// <param name="v">要查找的值</param>
        /// <returns></returns>
        protected static uint Divide_unsigned_b_table_binary_search(NumStr[] b_table, NumStr b, NumStr v)
        {
            uint h = 0, t = (uint)b_table.Length, m;

            do
            {
                m = (h + t) / 2;
                if (b_table[m] == null)
                {
                    b_table[m] = b * m;
                }
                var cpr = CompareAbsolute(v, b_table[m]);
                if (cpr == 0)
                {
                    return(m);
                }
                else if (cpr < 0)
                {
                    t = m - 1;
                }
                else
                {
                    h = m;
                }
            }while (t - h > 1);
            if (h == t)
            {
                return(h);
            }
            else
            {
                if (t == b_table.Length)
                {
                    return(h);
                }
                if (b_table[t] == null)
                {
                    b_table[t] = b * t;
                }
                if (CompareAbsolute(v, b_table[t]) < 0)
                {
                    if (b_table[h] == null)
                    {
                        b_table[h] = b * h;
                    }
                    return(h);
                }
                else
                {
                    return(t);
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// 开平方运算
        /// </summary>
        /// <param name="maxDecimalPlaces">答案保留小数位数</param>
        /// <returns></returns>
        protected override Digitable Sqrt(int maxDecimalPlaces)
        {
            NumStr a = new NumStr(this);

            if (a == null)
            {
                throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue);
            }
            //特殊情况
            if (a.IsNegative)
            {
                throw new IllegalOperationException();
            }
            else if (a.IsZero)
            {
                return(new NumStr(0, a.Space, maxDecimalPlaces));
            }

            //设进制为k,先将数字多次放大或缩小k^2倍,使其归一化为:1<=a<=k^2
            var one        = new NaturalNumStr(1, a.Space);
            var k2         = new NaturalNumStr(a.Space.NumberBase * a.Space.NumberBase, a.Space);
            var shiftTimes = 0;

            while (a < one)
            {
                a.RightShift(2);
                shiftTimes++;
            }
            while (a > k2)
            {
                a.LeftShift(2);
                shiftTimes--;
            }

            //平方根初值x
            var x = new NumStr(0, a.Space);
            //x当前的有效数字位数
            var nx = 0;
            //x^2初值
            var x2 = new NumStr(0, a.Space);
            //(x+1)^2的值
            NumStr x12;

            do
            {
                //用完全平方公式计算(y+1)^2
                x12 = x2 + x + x + one;
                if (a < x12)
                {
                    //本位枚举完成,开始枚举下一位
                    x.RightShift(1);  //x=x*k
                    nx++;
                    x2.RightShift(2); //x2=x2*k^2
                    a.RightShift(2);  //a=a*k^2
                }
                else
                {
                    //继续枚举
                    x  = x + one;
                    x2 = x12;
                }
            } while (nx < maxDecimalPlaces + 1 - shiftTimes && a != x12);
            x.LeftShift(x.IntegerPlaces + x.DecimalPlaces - 1 + shiftTimes);
            return(x);
        }
Beispiel #12
0
        /// <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);
        }
Beispiel #13
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);
        }
Beispiel #14
0
 /// <summary>
 /// 转换内部进制
 /// </summary>
 /// <param name="container">容器(原有数值会丢失)</param>
 /// <param name="numberBase">新的进制</param>
 /// <param name="value">新的数值(不会改变原有内容)</param>
 protected static void NumberBaseConversion(NumStr container, uint numberBase, NumStr value = null)
 {
     if (value == null)
     {
         value = new NumStr(container);
     }
     if (numberBase == value.NumberBase)
     {
         if (value.integerNumList != null)
         {
             container.integerNumList = new LinkedList <uint>();
             foreach (var i in value.integerNumList)
             {
                 container.integerNumList.AddLast(i);
             }
         }
         if (container.MaxDecimalPlaces > 0 && value.decimalNumList != null)
         {
             container.decimalNumList = new LinkedList <uint>();
             var i = value.decimalNumList.First;
             while (i != null && container.DecimalPlaces < container.MaxDecimalPlaces)
             {
                 container.decimalNumList.AddLast(i.Value);
                 i = i.Next;
             }
         }
     }
     else
     {
         //整数转换进制
         if (value.IntegerPlaces > 0)
         {
             //特殊情况:2的幂进制之间互相转换
             var i1 = tkTable.IndexOf(value.Space.NumberBase) + 1;
             var i2 = tkTable.IndexOf(numberBase) + 1;
             if (i1 > 0 && i2 > 0)
             {
                 if (i2 % i1 == 0)
                 {
                     //特殊方法:相邻位组合
                     container.integerNumList = new LinkedList <uint>();
                     int  q = i2 / i1, t = 0;
                     uint k = 1;
                     foreach (var v in value.integerNumList)
                     {
                         if (t == 0)
                         {
                             container.integerNumList.AddLast(0);
                             k = 1;
                         }
                         container.integerNumList.Last.Value += v * k;
                         t  = (t + 1) % q;
                         k *= value.NumberBase;
                     }
                 }
                 else
                 {
                     //普通方法:先转为2进制
                     NumStr tmp = null;
                     if (value.Space.NumberBase == 2)
                     {
                         tmp = value;
                     }
                     else
                     {
                         NumStr tmpNum = value;
                         var    two    = new NumStr(2, tmpNum.Space);
                         while (!tmpNum.IsZero)
                         {
                             var t = Mod(tmpNum, two, 0);
                             t.Item1.PositiveOrNegative = t.Item1.IsEmpty() ? 0 : 1;
                             if (tmp == null)
                             {
                                 tmp = new NumStr()
                                 {
                                     PositiveOrNegative = 1,
                                     integerNumList     = new LinkedList <uint>()
                                 }
                             }
                             ;
                             tmp.integerNumList.AddLast((uint)t.Item1.ToInt64());
                             tmpNum = t.Item2;
                         }
                     }
                     //再转换为目标进制,相邻位组合
                     if (numberBase == 2)
                     {
                         container.integerNumList = tmp.integerNumList;
                     }
                     else
                     {
                         container.integerNumList = new LinkedList <uint>();
                         int  t = 0;
                         uint k = 1;
                         foreach (var v in tmp.integerNumList)
                         {
                             if (t == 0)
                             {
                                 container.integerNumList.AddLast(0);
                                 k = 1;
                             }
                             container.integerNumList.Last.Value += v * k;
                             t  = (t + 1) % i2;
                             k *= 2;
                         }
                     }
                 }
             }
             else
             {
                 //普通方法:先转为默认进制
                 NumStr tmp;
                 if (value.Space.NumberBase == OperationSpace.DefaultSpace.NumberBase)
                 {
                     tmp = value;
                 }
                 else
                 {
                     var ni = value.integerNumList.First;
                     tmp = ni.Value;
                     NumStr nb = null;
                     for (var i = 1; i < value.IntegerPlaces; i++)
                     {
                         ni = ni.Next;
                         if (nb == null)
                         {
                             nb = value.NumberBase;
                         }
                         else
                         {
                             nb *= value.NumberBase;
                         }
                         tmp += ni.Value * nb;
                     }
                 }
                 //再转换为目标进制
                 LinkedList <uint> tmpList = null;
                 if (numberBase == OperationSpace.DefaultSpace.NumberBase)
                 {
                     tmpList = tmp.integerNumList;
                 }
                 else
                 {
                     var nb = new NumStr(numberBase, tmp.Space);
                     while (!tmp.IsZero)
                     {
                         var t = Mod(tmp, nb, 0);
                         t.Item1.PositiveOrNegative = CompareAbsolute(t.Item1, 0) == 0 ? 0 : 1;
                         if (tmpList == null)
                         {
                             tmpList = new LinkedList <uint>();
                         }
                         tmpList.AddLast((uint)t.Item1.ToInt64());
                         tmp = t.Item2;
                     }
                 }
                 container.integerNumList = tmpList;
             }
         }
         //小数转换进制
         if (container.MaxDecimalPlaces > 0 && value.DecimalPlaces > 0)
         {
             //先转为默认进制
             NumStr tmp = null;
             if (value.Space.NumberBase == OperationSpace.DefaultSpace.NumberBase)
             {
                 tmp = value;
             }
             else
             {
                 NumStr nb = new NumStr(1,
                                        container.MaxDecimalPlaces == OperationSpace.DefaultSpace.DefaultMaxDecimalPlaces ?
                                        OperationSpace.DefaultSpace
                     : new OperationSpace(container.MaxDecimalPlaces, OperationSpace.DefaultSpace.NumberBase));
                 tmp = new NumStr(0, nb.Space);
                 foreach (var ni in value.decimalNumList)
                 {
                     //todo: 用有理数类替换,提高精度
                     nb  /= value.NumberBase;
                     tmp += ni * nb;
                 }
             }
             //再转换为目标进制
             LinkedList <uint> tmpList = null;
             if (numberBase == OperationSpace.DefaultSpace.NumberBase)
             {
                 tmpList = tmp.decimalNumList;
             }
             else
             {
                 tmpList = new LinkedList <uint>();
                 var zeroCount = 0;  //记录小数末尾0的数量
                 var nb        = new NumStr(numberBase, tmp.Space);
                 do
                 {
                     tmp = new NumStr()
                     {
                         decimalNumList     = tmp.decimalNumList,
                         PositiveOrNegative = tmp.DecimalPlaces == 0 ? 0 : tmp.PositiveOrNegative,
                         MaxDecimalPlaces   = tmp.MaxDecimalPlaces,
                         Space = tmp.Space
                     };
                     tmp *= nb;
                     var v = (uint)tmp.ToInt64();
                     tmpList.AddLast(v);
                     if (v == 0)
                     {
                         zeroCount++;
                     }
                     else
                     {
                         zeroCount = 0;
                     }
                 }while (tmp.DecimalPlaces > 0 && tmpList.Count < container.MaxDecimalPlaces);
                 //去除小数末尾0
                 if (zeroCount == tmpList.Count)
                 {
                     tmpList = null;
                 }
                 else
                 {
                     for (var i = 0; i < zeroCount; i++)
                     {
                         tmpList.RemoveLast();
                     }
                 }
             }
             container.decimalNumList = tmpList;
         }
     }
 }
Beispiel #15
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);
                    }
                }
            }
        }
Beispiel #16
0
 /// <summary>
 /// 将两数进行比较,大于输出1,小于输出-1,等于输出0
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 /// <returns></returns>
 public static int CompareAbsolute(NumStr a, NumStr b) => a.CompareAbsolute(b);
Beispiel #17
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);
        }
Beispiel #18
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);
                }
            }
        }
Beispiel #19
0
 public bool Equals(NumStr other)
 {
     return(other != null && this == other && MaxDecimalPlaces == other.MaxDecimalPlaces);
 }
Beispiel #20
0
 /// <summary>
 /// 拷贝初始化
 /// </summary>
 /// <param name="num">原始对象</param>
 /// <param name="maxDecimalPlaces">最大保留小数位数</param>
 /// <param name="deep">是否为深拷贝</param>
 public NumStr(NumStr num, int?maxDecimalPlaces = null, bool deep = true)
     : base(num, maxDecimalPlaces)
 {
     Copy(num, maxDecimalPlaces, deep);
 }