Exemplo n.º 1
0
        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;
                }
            }
        }
Exemplo n.º 2
0
        // ---------------

        /// <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);
        }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 4
0
        /// <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);
        }
Exemplo n.º 5
0
        // ---------------------------------------
        // ---------------- 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());
        }
Exemplo n.º 6
0
        /// <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();
        }