/// <summary> /// 求两个数的最小公倍数。如果其中有个数为0,则返回0 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static NaturalNumStr LeastCommonMultiple(NaturalNumStr a, NaturalNumStr b) { if (a == null || b == null) { throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue); } //统一计算空间 if (a.Space != b.Space) { if (a.Space == OperationSpace.DefaultSpace) { a = (NaturalNumStr)a.ChangeOperationSpace(b.Space); } else if (b.Space == OperationSpace.DefaultSpace) { b = (NaturalNumStr)b.ChangeOperationSpace(a.Space); } else { throw new ProgramInterruptException(ProgramInterruptExceptionType.NotSameOperationSpace); } } if (a == 0 || b == 0) { return(new NaturalNumStr(0, a.Space)); } return(a * b / GreatestCommonDivisor(a, b)); }
/// <summary> /// 取模 /// </summary> /// <param name="a">被模数</param> /// <param name="b">模数</param> /// <returns>包含余数和商的元组</returns> public static (NaturalNumStr, NaturalNumStr) Mod(NaturalNumStr a, NaturalNumStr b) { var ans = a.Mod_unsigned(b, 0); var new_ans = (new NaturalNumStr(ans.Item1 as NumStr, false), new NaturalNumStr(ans.Item2 as NumStr, false)); new_ans.Item1.PositiveOrNegative = new_ans.Item1.IsEmpty() ? 0 : 1; new_ans.Item2.PositiveOrNegative = new_ans.Item2.IsEmpty() ? 0 : 1; return(new_ans); }
/// <summary> /// 输出将该数去掉小数点以后的数 /// </summary> /// <returns></returns> public NaturalNumStr RemoveDecimalPoint() { var n = new NaturalNumStr(0, Space); if (IsZero) { return(n); } else { n.integerNumList = new LinkedList <uint>(); n.PositiveOrNegative = 1; } if (decimalNumList != null) { if (integerNumList == null) { var i = decimalNumList.GetEnumerator(); //跳过高位0 do { i.MoveNext(); }while (i.Current == 0); do { n.integerNumList.AddFirst(i.Current); }while (i.MoveNext()); return(n); } else { foreach (var i in decimalNumList) { n.integerNumList.AddFirst(i); } } } if (integerNumList != null) { foreach (var i in integerNumList) { n.integerNumList.AddLast(i); } } return(n); }
/// <summary> /// 求两个数的最大公约数。如果其中一个数为0、另一个不为0,则返回不为0的那个数 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static NaturalNumStr GreatestCommonDivisor(NaturalNumStr a, NaturalNumStr b) { if (a == null || b == null) { throw new ProgramInterruptException(ProgramInterruptExceptionType.IllegalValue); } var old_a = a; var old_b = b; //统一计算空间 if (a.Space != b.Space) { if (a.Space == OperationSpace.DefaultSpace) { a = (NaturalNumStr)a.ChangeOperationSpace(b.Space); } else if (b.Space == OperationSpace.DefaultSpace) { b = (NaturalNumStr)b.ChangeOperationSpace(a.Space); } else { throw new ProgramInterruptException(ProgramInterruptExceptionType.NotSameOperationSpace); } } if (a == 0) { if (b == 0) { throw new IllegalOperationException(); } else { if (ReferenceEquals(b, old_b)) { return(new NaturalNumStr(b)); } else { return(b); } } } else if (b == 0) { if (ReferenceEquals(a, old_a)) { return(new NaturalNumStr(a)); } else { return(a); } } if (b > a) { var t = a; a = b; b = t; } //辗转相除法 while (!b.IsZero) { var t = a; a = b; b = t % b; } if (ReferenceEquals(a, old_a) || ReferenceEquals(a, old_b)) { return(new NaturalNumStr(a)); } else { return(a); } }
/// <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); }