/// <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); }
/// <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); } } }