public static void baseConvert(IList <int> from, IList <int> to, int fromBase, int newBase) { // проверяем, не кратное ли основание int?power; if (WhiteMath <int, CalcInt> .IsNaturalIntegerPowerOf(fromBase, newBase, out power) || WhiteMath <int, CalcInt> .IsNaturalIntegerPowerOf(newBase, fromBase, out power)) { convertPowered(from, to, fromBase, newBase, power.Value); } // в противном случае - не избежать последовательного деления. else { int k = 0; IList <int> divide = from; while (divide.CountSignificant() > 1 || divide[0] > 0) { int remainder; divide = LongIntegerMethods.DivideByInteger(fromBase, divide, newBase, out remainder); to[k++] = remainder; } } }
// --------------- /// <summary> /// Used with long integers digit arrays. Cuts the incoming list /// so that it contains only significant digits. /// </summary> /// <param name="list">The incoming digits list.</param> /// <returns>The list without leading zeroes.</returns> public static Numeric <T, C>[] Cut <T, C>(this IList <Numeric <T, C> > list) where C : ICalc <T>, new() { Numeric <T, C>[] newList = new Numeric <T, C> [list.CountSignificant()]; General.ServiceMethods.Copy(list, 0, newList, 0, newList.Length); return(newList); }
/// <summary> /// Used with long integers digit arrays. Cuts the incoming list /// so that it contains only significant digits. /// </summary> /// <param name="list">The incoming digits list.</param> /// <returns>The list without leading zeroes.</returns> public static int[] Cut(this IList <int> list) { int[] newList = new int[list.CountSignificant()]; General.ServiceMethods.Copy(list, 0, newList, 0, newList.Length); return(newList); }
/// <summary> /// Creates a new instance of Polynom object basing on the coefficients /// array. /// </summary> /// <param name="coefficients"></param> public Polynom(IList <Numeric <T, C> > coefficients) { // Нули при старших степенях нас не интересуют. int countSignificant = coefficients.CountSignificant(); this.coefficients = new Numeric <T, C> [countSignificant]; General.ServiceMethods.Copy(coefficients, 0, this.coefficients, 0, countSignificant); }
// --------------------------------------- // ---------------- DIVISION ------------- // --------------------------------------- /// <summary> /// Performs the division (with remainder) of two long integer numbers. /// Returns the quotient containing only significant digits. /// /// The remainder containing only significant digits is passed as an 'out' parameter. /// </summary> /// <param name="BASE">The digit base integers to divide one by another.</param> /// <param name="one">The dividend.</param> /// <param name="two">The divisor.</param> /// <param name="remainder">The reference to store the remainder.</param> /// <returns>The quotient containing only significant digits (no trailing zeroes).</returns> public static IList <int> Div(int BASE, IList <int> one, IList <int> two, out IList <int> remainder) { Contract.Requires <ArgumentNullException>(one != null, "one"); Contract.Requires <ArgumentNullException>(two != null, "two"); Contract.Ensures(Contract.Result <IList <int> >() != null); // result's not null Contract.Ensures(Contract.ValueAtReturn <IList <int> >(out remainder) != null); // remainder's not null Contract.Ensures(Contract.ForAll(Contract.Result <IList <int> >(), (x => (x >= 0)))); // the result has positive digits Contract.Ensures(Contract.ForAll(Contract.ValueAtReturn <IList <int> >(out remainder), (x => (x >= 0)))); // the remainder has positive digits int[] result = new int[one.CountSignificant() - two.CountSignificant() + 1]; remainder = Div(BASE, result, one, two).Cut(); return(result.Cut()); }
/// <summary> /// Performs the division (with remainder) of two long integer numbers. /// The method would return the list containing the remainder digits. /// </summary> /// <returns>The list containing the remainder digits.</returns> /// <param name="BASE">The numberic base of the digits, ex. 10 000</param> /// <param name="result">The digits array to store the result. WARNING! Should be able to store AT LEAST one.Count - two.Count + 1 digits.</param> /// <param name="one">The digits array containing the first operand.</param> /// <param name="two">The digits array containing the second operand.</param> public static IList <int> Div(int BASE, IList <int> result, IList <int> one, IList <int> two) { Contract.Requires <ArgumentNullException>(result != null, "result"); Contract.Requires <ArgumentNullException>(one != null, "one"); Contract.Requires <ArgumentNullException>(two != null, "two"); Contract.Requires(Contract.ForAll(one, x => x >= 0)); // first contains only positive digits Contract.Requires(Contract.ForAll(two, x => x >= 0)); // second contains only positive digits Contract.Ensures(Contract.Result <IList <int> >() != null); // remainder's not null Contract.Ensures(Contract.ForAll(Contract.Result <IList <int> >(), x => x >= 0)); // remainder has positive digits Contract.Ensures(Contract.ForAll(result, x => x >= 0)); // quot has positive digits // Обнуляем результат result.FillByAssign(0); // ------------------ IList <int> u, v; int uShift, vShift, i; long temp, temp1, temp2; int scale; int qGuess, remainder; int borrow, carry; // Проверим, надо ли домножать. // Если да - увы, надо выделять дополнительную память. scale = BASE / (two[two.CountSignificant() - 1] + 1); if (scale > 1) { u = new int[one.Count + 2]; v = new int[two.Count + 2]; int[] scaleAr = new int[] { scale }; MultiplySimple(BASE, u, one, scaleAr); MultiplySimple(BASE, v, two, scaleAr); } else { // Число будет "портиться", поэтому нужно создать хоть копию. u = new int[one.CountSignificant() + 1]; General.ServiceMethods.Copy(one, 0, u, 0, u.Count - 1); // Делитель портиться не будет. v = two; } // ------------ int n = v.CountSignificant(); int m = u.CountSignificant() - n; // ------------ // Добавлено -1 for (vShift = m, uShift = n + vShift; vShift >= 0; --vShift, --uShift) { qGuess = (int)(((long)u[uShift] * BASE + u[uShift - 1]) / v[n - 1]); remainder = (int)(((long)u[uShift] * BASE + u[uShift - 1]) % v[n - 1]); while (remainder < BASE) { temp2 = (long)v[n - 2] * qGuess; temp1 = (long)remainder * BASE + u[uShift - 2]; if ((temp2 > temp1) || (qGuess == BASE)) { --qGuess; remainder += v[n - 1]; } else { break; } } // Теперь qGuess - правильное частное или на единицу больше q // Вычесть делитель B, умноженный на qGuess из делимого U, // начиная с позиции vJ+i carry = 0; borrow = 0; // цикл по цифрам two for (i = 0; i < n; i++) { // получить в temp цифру произведения B*qGuess temp1 = (long)v[i] * qGuess + carry; carry = (int)(temp1 / BASE); temp1 -= (long)carry * BASE; // Сразу же вычесть из U temp2 = (long)u[i + vShift] - temp1 + borrow; if (temp2 < 0) { u[i + vShift] = (int)(temp2 + BASE); borrow = -1; } else { u[i + vShift] = (int)temp2; borrow = 0; } } // возможно, умноженое на qGuess число B удлинилось. // Если это так, то после умножения остался // неиспользованный перенос carry. Вычесть и его тоже. temp2 = (long)u[i + vShift] - carry + borrow; if (temp2 < 0) { u[i + vShift] = (int)temp2 + BASE; borrow = -1; } else { u[i + vShift] = (int)temp2; borrow = 0; } // Прошло ли вычитание нормально ? if (borrow == 0) { // Да, частное угадано правильно result[vShift] = qGuess; } else { // Нет, последний перенос при вычитании borrow = -1, // значит, qGuess на единицу больше истинного частного result[vShift] = qGuess - 1; // добавить одно, вычтенное сверх необходимого B к U carry = 0; for (i = 0; i < n; i++) { temp = (long)u[i + vShift] + v[i] + carry; if (temp >= BASE) { u[i + vShift] = (int)(temp - BASE); carry = 1; } else { u[i + vShift] = (int)temp; carry = 0; } } u[i + vShift] = u[i + vShift] + carry - BASE; } // Обновим размер U, который после вычитания мог уменьшиться // i = u.Length - 1; // while ((i > 0) && (u[i] == 0)) // u.digits.RemoveAt(i--); } // Возвращаем остаток. // Только надо поделить на scale. int[] remDigits = new int[u.Count]; LongIntegerMethods.DivideByInteger(BASE, remDigits, u, scale); return(remDigits); }
/// <summary> /// Performs the division (with remainder) of two long integer numbers. /// The method would return the list containing the remainder digits. /// </summary> /// <returns>The list containing the remainder digits.</returns> /// <param name="BASE">The numberic base of the digits, ex. 10 000</param> /// <param name="result">The digits array to store the result. WARNING! Should be able to store AT LEAST one.Count - two.Count + 1 digits.</param> /// <param name="one">The digits array containing the first operand.</param> /// <param name="two">The digits array containing the second operand.</param> public static IList<int> Div(int BASE, IList<int> result, IList<int> one, IList<int> two) { Contract.Requires<ArgumentNullException>(result != null, "result"); Contract.Requires<ArgumentNullException>(one != null, "one"); Contract.Requires<ArgumentNullException>(two != null, "two"); Contract.Requires(Contract.ForAll(one, x => x >= 0)); // first contains only positive digits Contract.Requires(Contract.ForAll(two, x => x >= 0)); // second contains only positive digits Contract.Ensures(Contract.Result<IList<int>>() != null); // remainder's not null Contract.Ensures(Contract.ForAll(Contract.Result<IList<int>>(), x => x >= 0)); // remainder has positive digits Contract.Ensures(Contract.ForAll(result, x => x >= 0)); // quot has positive digits // Обнуляем результат result.FillByAssign(0); // ------------------ IList<int> u, v; int uShift, vShift, i; long temp, temp1, temp2; int scale; int qGuess, remainder; int borrow, carry; // Проверим, надо ли домножать. // Если да - увы, надо выделять дополнительную память. scale = BASE / (two[two.CountSignificant() - 1] + 1); if (scale > 1) { u = new int[one.Count + 2]; v = new int[two.Count + 2]; int[] scaleAr = new int[] { scale }; MultiplySimple(BASE, u, one, scaleAr); MultiplySimple(BASE, v, two, scaleAr); } else { // Число будет "портиться", поэтому нужно создать хоть копию. u = new int[one.CountSignificant() + 1]; General.ServiceMethods.Copy(one, 0, u, 0, u.Count - 1); // Делитель портиться не будет. v = two; } // ------------ int n = v.CountSignificant(); int m = u.CountSignificant() - n; // ------------ // Добавлено -1 for (vShift = m, uShift = n + vShift; vShift >= 0; --vShift, --uShift) { qGuess = (int)(((long)u[uShift] * BASE + u[uShift - 1]) / v[n - 1]); remainder = (int)(((long)u[uShift] * BASE + u[uShift - 1]) % v[n - 1]); while (remainder < BASE) { temp2 = (long)v[n - 2] * qGuess; temp1 = (long)remainder * BASE + u[uShift - 2]; if ((temp2 > temp1) || (qGuess == BASE)) { --qGuess; remainder += v[n - 1]; } else break; } // Теперь qGuess - правильное частное или на единицу больше q // Вычесть делитель B, умноженный на qGuess из делимого U, // начиная с позиции vJ+i carry = 0; borrow = 0; // цикл по цифрам two for (i = 0; i < n; i++) { // получить в temp цифру произведения B*qGuess temp1 = (long)v[i] * qGuess + carry; carry = (int)(temp1 / BASE); temp1 -= (long)carry * BASE; // Сразу же вычесть из U temp2 = (long)u[i + vShift] - temp1 + borrow; if (temp2 < 0) { u[i + vShift] = (int)(temp2 + BASE); borrow = -1; } else { u[i + vShift] = (int)temp2; borrow = 0; } } // возможно, умноженое на qGuess число B удлинилось. // Если это так, то после умножения остался // неиспользованный перенос carry. Вычесть и его тоже. temp2 = (long)u[i + vShift] - carry + borrow; if (temp2 < 0) { u[i + vShift] = (int)temp2 + BASE; borrow = -1; } else { u[i + vShift] = (int)temp2; borrow = 0; } // Прошло ли вычитание нормально ? if (borrow == 0) { // Да, частное угадано правильно result[vShift] = qGuess; } else { // Нет, последний перенос при вычитании borrow = -1, // значит, qGuess на единицу больше истинного частного result[vShift] = qGuess - 1; // добавить одно, вычтенное сверх необходимого B к U carry = 0; for (i = 0; i < n; i++) { temp = (long)u[i + vShift] + v[i] + carry; if (temp >= BASE) { u[i + vShift] = (int)(temp - BASE); carry = 1; } else { u[i + vShift] = (int)temp; carry = 0; } } u[i + vShift] = u[i + vShift] + carry - BASE; } // Обновим размер U, который после вычитания мог уменьшиться // i = u.Length - 1; // while ((i > 0) && (u[i] == 0)) // u.digits.RemoveAt(i--); } // Возвращаем остаток. // Только надо поделить на scale. int[] remDigits = new int[u.Count]; LongIntegerMethods.DivideByInteger(BASE, remDigits, u, scale); return remDigits; }
// --------------------------------------- // ---------------- DIVISION ------------- // --------------------------------------- /// <summary> /// Performs the division (with remainder) of two long integer numbers. /// Returns the quotient containing only significant digits. /// /// The remainder containing only significant digits is passed as an 'out' parameter. /// </summary> /// <param name="BASE">The digit base integers to divide one by another.</param> /// <param name="one">The dividend.</param> /// <param name="two">The divisor.</param> /// <param name="remainder">The reference to store the remainder.</param> /// <returns>The quotient containing only significant digits (no trailing zeroes).</returns> public static IList<int> Div(int BASE, IList<int> one, IList<int> two, out IList<int> remainder) { Contract.Requires<ArgumentNullException>(one != null, "one"); Contract.Requires<ArgumentNullException>(two != null, "two"); Contract.Ensures(Contract.Result<IList<int>>() != null); // result's not null Contract.Ensures(Contract.ValueAtReturn<IList<int>>(out remainder) != null); // remainder's not null Contract.Ensures(Contract.ForAll(Contract.Result<IList<int>>(), (x => (x >= 0)))); // the result has positive digits Contract.Ensures(Contract.ForAll(Contract.ValueAtReturn<IList<int>>(out remainder), (x => (x >= 0)))); // the remainder has positive digits int[] result = new int[one.CountSignificant() - two.CountSignificant() + 1]; remainder = Div(BASE, result, one, two).Cut(); return result.Cut(); }