|
Программирование >> Немодифицирующие последовательные алгоритмы
if (Р[0] / а != b) { P.push back(0); DDproductIa, b, P[l], P[0]); reduce(); neg = DifSigns, return *this; if (L == 1) && Ly > 1 { uint digit = P[0] ; *this = y; Поменять местами операнды *this *= digit; и вызвать operator*=(uint у) } else if (Ly == 1) && L > 1 { *this *= y.P[0]; Вызвать operator*=(uint y) } else Длины обоих операндов L и Ly больше 1: { int lenProd = L + Ly, i, jA, jB; uint sumHi = 0, sumLo, Hi, Lo, sumLoOld, sumHiOld, carry=0; large x = *this; SetLen(lenProd); Установить длину *this равной lenProd for (i=0; i<lenProd; i++) { sumLo = sumHi; sumHi = carry; carry = 0; int max jA = min(i, L-1); jA <= i гарантирует jB >= 0 jA < L, поскольку в *this имеется лишь L цифр for (jA=max(0, i+l-Ly); jA<=max jA; jA++) jA > i - Ly гарантирует jB < Ly { jB = i - jA; Другое произведение цифр, влияющее на позицию i (= jA + jB) произведения всего числа: DDproduct(х.Р[jA], y.P[jB], Hi, Lo); sumLoOld = sumLo; sumHiOld = sumHi; sumLo += Lo; if (sumLo < sumLoOld) sumHi++; sumHi += Hi; carry += (sumHi < sumHiOld); P[i] = sumLo; reduce(); neg = DifSigns; large &large: :operator = (uint k) { int q = к / wLen; Количество полных слов, if (q) { int i; Увеличить длину на q: SetLen(P.size() + q); Сдвинуть *this на q слов влево: for (i=P.size()-l; i>=0; i--) P[i] = (i < q ? 0 : P[i - q] ) ; к %= wLen; Теперь к содержит оставшиеся } позиции сдвига. if (к) О < к < wLen: { int kl = wLen - к; uint mask = (1 к) - 1; маска: 00..Oil..1 (к единичных бит) SetLen(Р.size() + 1); Каждый из P[i] сдвигается на к позиций влево, а затем комбинируется по или с к самыми левыми битами правого соседа P[i-1]: for (int i=P.size()-1; i>=0; i--) { P[i] = k; if (i > 0) P[i] 1= (P[i-1] kl) & mask; reduce(); return *this; return *this; large &large::operator/=(const large &divisor) { large r; Разделить *this на делитель, сохраняя результат в *this; О означает, что остаток в г не обязан быть правильным: divide(divisor, *this, г, 0) ; return *this; large &large::operator%=(const large &divisor) { large q; Разделить *this на делитель, сохраняя результат в *this; 1 означает, что остаток в г должен быть правильным: divide(divisor, q, *this, 1); return *this; large &large::operator>>=(uint k) Аналогично = { int q = к / wLen, L = P.sizeO; if (q >= L){*this = 0; return *this;} if (q) { for (int i=q; i<L; i++) P[i-q] = P[i]; SetLen(L - q); к %= wLen; if (k == 0) {reduced; return *this;} int n = P.sizeO - 1, kl = wLen - k; uint mask = (1 k) - 1; for (int i=0; i<=n; i++) { P[i] = k; if (i < n) P[i] 1= ((P[i+1] & mask) kl); reduce(); return *this; compare возвращает: отрицательное число, если *this < у, ноль, если *this == у, и положительное, если *this > у. int large::compare(const large &y)const { if (neg != y.neg) return y.neg - neg; int code = 0, L = P.size(), Ly = y.P.sizeO; if (L == 0 II Ly == 0) code = L - Ly; else if (L < Ly) code = -1; else if (L > Ly) code = +1; else for (int i = L - 1; i >= 0; i--) { if (P[i] > y.P[i]) {code = 1; break;} else if (P[i] < y.P[i]) {code = -1; break;} return neg ? -code : code; Двуцифровое произведение (Hi, Lo) = A * B: void large::DDproduct(uint A, uint B, uint &Hi, uint &Lo)const { uint hiA = A hLen, loA = A & rMask, hiB = В hLen, loB = В & rMask, midl, mid2, old; Lo = loA * loB; Hi = hiA * hiB; midl = loA * hiB; mid2 = hiA * loB; old = Lo; Lo += midl hLen; Hi += (Lo < old) + (midl >> hLen); old = Lo; Lo += mid2 hLen; Hi += (Lo < old) + (mid2 hLen);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |