/// <summary> /// Calculates a product of a two ALong instances, a.k.a "School" method (very slow) /// </summary> /// <param name="num1">Multiplicand</param> /// <param name="num2">Multiplier</param> /// <returns>Product of num1 and num2.</returns> //TODO: replace with Karatsuba, Schönhage–Strassen or Knuth. (Fast Fourier transform?). //TODO: use base of size of Int32 to "shorten" sizes of numbers within multiplication speed being kept. public static ALong Mul(ALong num1, ALong num2) { var result = new ALong(0); if (num1 == 0 || num2 == 0) { return(result); } var carry = 0; for (int i = 0; i < num1.Length(); i++) { var n1 = num1.GetRNumAtIndex(i); var res = String.Empty; var n2len = num2.Length(); carry = 0; for (int k = 0; k < n2len; k++) { var n2 = num2.GetRNumAtIndex(k); var ns = n1 * n2 + carry; carry = ns / 10; res = (ns % 10) + res; if (k == n2len - 1 && carry > 0) { res = carry.ToString() + res; } } var mulres = new ALong(res); mulres.MulBase(i); result += mulres; } if (num1.IsNegative != num2.IsNegative) { result.SetNegative(true); } return(result); }
/// <summary> /// Calculates a quotient and remainder of division of a two ALong instances. /// </summary> /// <param name="num1">Divident</param> /// <param name="num2">Divisor</param> /// <returns>A Tuple of Quotient and Remainder.</returns> public static Tuple <ALong, ALong> Divide(ALong num1, ALong num2) { var num2a = Abs(num2); if (num2a < Int32.MaxValue) { return(DivInt(num1, num2.ToString().ToInt())); } if (num2 == 0) { throw new ArgumentException("Division by zero"); } if (num1 == 0) { return(new Tuple <ALong, ALong>(new ALong(0), new ALong(0))); } var num1a = Abs(num1); if (num1a == num2a) { return(new Tuple <ALong, ALong>(new ALong(1).SetNegative(num1.IsNegative != num2.IsNegative), new ALong(0))); } if (num1a < num2a) { return(new Tuple <ALong, ALong>(new ALong(0), new ALong(num1))); } var b = 10; // base var down = new ALong(0); // Get upper limit var up = new ALong(b); while (num1a > num2a * up) { up = up * b; } // Divide while (up - down > 1) { var cur = (down + up) / 2; var c = num2a * (cur); if (c < num1a) { down = cur; continue; } if (c > num1a) { up = cur; continue; } if (c == num1a) { down = cur; up = cur; continue; } } var remainder = num1a - down * num2a; down.SetNegative(num1.IsNegative != num2.IsNegative); remainder.SetNegative(num1.IsNegative); return(new Tuple <ALong, ALong>(down, remainder)); }