public static int GetDivisorCountLarge(LargeNumber n) { LargeNumber half = n / 2 + 1; HashSet <LargeNumber> divisors = new HashSet <LargeNumber>(); for (LargeNumber i = 2; n > 1;) { LargeNumber quotient = LargeNumber.Divide(n, i, out LargeNumber remainder); if (remainder == 0) { Debug.Write(i.ToString() + " "); LargeNumber[] divisorsToAdd = divisors.Select(d => d * i).ToArray(); foreach (LargeNumber divisorToAdd in divisorsToAdd) { //Debug.Write(divisorToAdd.ToString() + " "); divisors.Add(divisorToAdd); } divisors.Add(i); n = quotient; } else { i = i + 1; } } divisors.Add(1); Debug.Print(""); Debug.Print(string.Join(", ", divisors.OrderBy(d => d).Select(d => d.ToString()))); return(divisors.Count); }
public static LargeNumber Multiply(LargeNumber x, LargeNumber y) { if (IsZero(x) || IsZero(y)) { return(0); } LargeNumber result = new LargeNumber(); for (int i = 0; i < y._digits.Count; i++) { byte yDigit = y._digits[y._digits.Count - i - 1]; if (yDigit != 0) { LargeNumber partialProd = MultiplyByOneDigit(x, yDigit); for (int j = 0; j < i; j++) { partialProd._digits.Add(0); } result = AddPositives(result, partialProd); } } result._sign = x._sign * y._sign; return(result); }
private static LargeNumber AddPositives(LargeNumber x, LargeNumber y) { LargeNumber result = new LargeNumber(); int maxDigits = Math.Max(x._digits.Count, y._digits.Count); result._digits = new List <byte>(maxDigits + 1); int carry = 0; for (int i = 0; i < maxDigits; i++) { int digitSum = carry; if (x._digits.Count - 1 - i >= 0) { digitSum += x._digits[x._digits.Count - 1 - i]; } if (y._digits.Count - 1 - i >= 0) { digitSum += y._digits[y._digits.Count - 1 - i]; } result._digits.Insert(0, (byte)(digitSum % 10)); carry = digitSum / 10; } if (carry > 0) { result._digits.Insert(0, (byte)carry); } return(result); }
public static void RunTests() { LargeNumber n1 = 2589; LargeNumber n2 = 2; LargeNumber n3 = -10; LargeNumber zero = 0; LargeNumber n = 0; Debug.Assert(n == zero); Debug.Assert(zero + zero == zero); Debug.Assert(-zero == zero); Debug.Assert(zero.Equals(-zero)); Debug.Assert(-(LargeNumber)(-20) == 20); Debug.Assert(n1 + zero == n1); Debug.Assert(n3 + zero == n3); Debug.Assert(n3 - zero == n3); Debug.Assert(n1 + n2 == 2591); Debug.Assert(zero - n2 == -2); Debug.Assert(n2 - n3 == 12); Debug.Assert(n1 - n1 == zero); Debug.Assert(n1 - n2 == 2587); Debug.Assert(n2 - n1 == -2587); Debug.Assert(n3 - n2 == -12); Debug.Assert(n3 - n3 == 0); Debug.Assert(n3 + n3 == -20); Debug.Assert(n1 * zero == zero); Debug.Assert(zero * n3 == zero); Debug.Assert(n1 * 2 == 5178); Debug.Assert(n1 * 1 == n1); Debug.Assert((LargeNumber)5477 * (LargeNumber)(-19903) == 5477 * (-19903)); Debug.Assert((LargeNumber)23169 * 3103 == 71893407); Debug.Assert(n3 < 0); Debug.Assert(n2 > 0); Debug.Assert(n1 > n3); Debug.Assert(n2 > n3); Debug.Assert(n2 == 2); Debug.Assert(zero / 13 == 0); Debug.Assert(zero / 1 == 0); Debug.Assert(n1 / 1 == n1); Debug.Assert(n1 / n1 == 1); Debug.Assert(n1 / 1 == n1); Debug.Assert(n1 / n2 == (2589 / 2)); Debug.Assert(n1 / n3 == (2589 / -10)); Debug.Assert((LargeNumber)1000 / 10 == 100); Debug.Assert((LargeNumber)1000 / 20 == 50); Debug.Assert((LargeNumber)1689 / 20 == (1689 / 20)); Debug.Assert((LargeNumber)3689900342 / 4591 == (3689900342 / 4591)); Debug.Assert((LargeNumber)"969696969696969696969696969696" / 3 == (LargeNumber)"323232323232323232323232323232"); Debug.Assert((LargeNumber)9487235 % 2 == 1); Debug.Assert((LargeNumber)"8349438234943823293578234654239452348558" % 2 == 0); Debug.Assert((LargeNumber)9487235648 % 782 == (9487235648 % 782)); }
public static LargeNumber Power(LargeNumber @base, int exp) { LargeNumber result = 1; for (int i = 0; i < exp; i++) { result = result * @base; } return(result); }
private static LargeNumber GetFirstDividend(LargeNumber dividend, LargeNumber divisor) { int divisorLength = divisor._digits.Count; LargeNumber result = new LargeNumber(dividend._digits.Take(divisorLength)); if (result < divisor) { result = new LargeNumber(dividend._digits.Take(divisorLength + 1)); } return(result); }
public LargeNumber(LargeNumber n) { if (n._digits != null) { _digits = new List <byte>(n._digits); } else { _digits = new List <byte>(); } _sign = n._sign; }
public static LargeNumber Divide(LargeNumber dividend, LargeNumber divisor, out LargeNumber remainder) { if (divisor == 0) { throw new DivideByZeroException(); } if (dividend == 0 || divisor == 1) { remainder = 0; return(new LargeNumber(dividend)); } if (dividend < divisor) { remainder = new LargeNumber(dividend); return(0); } LargeNumber result = new LargeNumber(); int dividendSign = dividend._sign; int divisorSign = divisor._sign; try { // Make the numbers positive, so it's easier to divide them. dividend._sign = 1; divisor._sign = 1; LargeNumber partialDividend = GetFirstDividend(dividend, divisor); int digit = GetLargestMultiplier(partialDividend, divisor, out remainder); result._digits.Add((byte)digit); for (int i = partialDividend._digits.Count; i < dividend._digits.Count; i++) { partialDividend = new LargeNumber(remainder._digits.Concat(dividend._digits.Skip(i).Take(1))); digit = GetLargestMultiplier(partialDividend, divisor, out remainder); result._digits.Add((byte)digit); } } finally { // Restore the numbers signs dividend._sign = dividendSign; divisor._sign = divisorSign; } result._sign = dividend._sign * divisor._sign; return(result); }
private static LargeNumber Normalize(LargeNumber n) { LargeNumber result = new LargeNumber(n); // Trim leading zeroes result._digits = n._digits.SkipWhile(b => b == 0).ToList(); // Set sign for zero if (IsZero(result)) { result._sign = 1; } return(result); }
private static int GetLargestMultiplier(LargeNumber dividend, LargeNumber divisor, out LargeNumber remainder) { for (int multiplier = 9; multiplier >= 1; multiplier--) { LargeNumber multResult = Multiply(divisor, multiplier); remainder = dividend - multResult; if (remainder >= 0) { return(multiplier); } } remainder = dividend; return(0); }
private static LargeNumber SubtractPositives(LargeNumber x, LargeNumber y) { bool isFirstBiggerThanSecond = x >= y; LargeNumber n1 = isFirstBiggerThanSecond ? x : y; LargeNumber n2 = isFirstBiggerThanSecond ? y : x; Debug.Assert(y >= 0); LargeNumber result = new LargeNumber(); int maxDigits = n1._digits.Count; result._digits = new List <byte>(maxDigits); int carry = 0; for (int i = 0; i < maxDigits; i++) { int digit1 = n1._digits[n1._digits.Count - 1 - i] + carry; int digit2 = (n2._digits.Count - 1 - i >= 0) ? n2._digits[n2._digits.Count - 1 - i] : 0; if (digit2 > digit1) { digit1 += 10; carry = -1; } else { carry = 0; } int digitSum = digit1 - digit2; result._digits.Insert(0, (byte)(digitSum)); } if (!isFirstBiggerThanSecond) { result._sign = -1; } return(result); }
private static LargeNumber MultiplyByOneDigit(LargeNumber x, byte y) { if (IsZero(x) || y == 0) { return(0); } LargeNumber result = new LargeNumber(); int carry = 0; for (int i = 0; i < x._digits.Count; i++) { int prod = x._digits[x._digits.Count - i - 1] * y + carry; result._digits.Insert(0, (byte)(prod % 10)); carry = prod / 10; } if (carry > 0) { result._digits.Insert(0, (byte)carry); } return(result); }
private static bool IsZero(LargeNumber n) { return(n._digits.All(d => d == 0)); }
public static LargeNumber operator %(LargeNumber n1, LargeNumber n2) { LargeNumber n = Divide(n1, n2, out LargeNumber remainder); return(remainder); }