/// <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); }
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"); }
/// <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); }
/// <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);
/// <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); }
public int Compare(Digitable a, Digitable b) { // todo:比较任意两个数字的大小 throw new System.Exception(); }
/// <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); } } } }
/// <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); }
/// <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); } } }