Для удобства пользователей был введен еще один метод vishislenie(), который предоставляет возможность выполнять вышеперечисленные арифметические операции с двумя или одним большим числом путем простого ввода необходимого для вычисления выражения. Пример работы данного метода приведен на рисунке 9.
факториал большой число перемножение
1. Лаптев В.В., Морозов А.В. «Объектно-ориентированное программирование. Задачи и упражнения». Издательство: «Питер» 2007 г.
2. Лафоре Р. «Объектно-ориентированное программирование в С++». Издательство: «Питер», 2004 г.
Листинг 1. Файл BigInteger.h класс BigInteger.
#include <iostream>
#include <deque> // очередь (избиблиотеки STL)
#include <string>
using namespace std;
class BigInteger {
deque<int> vect; // «содержит» число
char znak; // знак числа
public: BigInteger()
{
vect = deque<int>();
znak = ' ';
}
// ___________________ Сравнение модулей больших чисел____________
int sravnenie (BigInteger big1, BigInteger big2)
{
if (big1.vect.size() > big2.vect.size()) return 1; // 1, еслипервоечисло > второго
if (big1.vect.size() < big2.vect.size()) return -1; // -1, еслипервоечисло < второго
if (big1.vect.size() == big2.vect.size())
{
for (int i = 0; i < (int) big1.vect.size(); i++)
{
if (big1.vect.at(i) > big2.vect.at(i)) return 1;
if (big1.vect.at(i) < big2.vect.at(i)) return -1;
}
return 0; // 0, если числа равны
}
}
// ___________________ Чтение числа из консоли ___________________
BigInteger chtenie()
{
BigInteger big;
string temp = «0123456789»; // вспомогательнаястрока
string minus = «–»;
string str;
cin >> str;
if (str.at(0) == minus.at(0)) big.znak = '-'; // определение знака числа
for (int i = 0; i < (int) str.length(); i++) // циклсчитывающийцифрыизстроки
for (int j = 0; j < 10; j++)
if (str.at(i) == temp.at(j)) big.vect.push_back(j);
return dell_null(big);
}
// ___________________ Функция удаления нулей из начала числа ____
BigInteger dell_null (BigInteger big)
{
while (big.vect.size() > 1)
{
if (big.vect.at(0)!= 0) break;
else {big.vect.pop_front();}
}
return big;
}
// ___________________ Печать числа в консоль ____________________
void vector_print (BigInteger big)
{
big = dell_null(big); // убираем нули из начала числа
if (big.vect.size() == 1 && big.vect.at(0) == 0) big.znak = ' '; // если число равно 0, то не ставим знак
if (big.znak == '-') // если число отрицательное, сначала печатаем знак –
cout << big.znak;
for (int i = 0; i < (int) big.vect.size(); i++)
cout << big.vect.at(i);
}
// ___________________ Суммабольшихчисел _______________________
BigInteger summa (BigInteger big1, BigInteger big2)
{
if (big1.znak!= big2.znak) // если разные знаки, то отправляем на метод разность
{
if (big1.znak == '-') // заменяем– x+y на y-x
{
big1.znak = ' ';
return rasnost (big2, big1);
}
else // заменяем x+-y на x-y
{
big2.znak = ' ';
return rasnost (big1, big2);
}
}
deque<int> summa = deque<int>(); // сюда записывается результат
int temp = 0; // 1 для добавления к старшему разряду
int metka = 0; // для вычисления позиции, с которой остаются разряды только одного числа
if (big1.vect.size() >= big2.vect.size()) // ставим большее число на первое место
{
for (int i = big1.vect.size() – 1, j = big2.vect.size() – 1; j >=0; i–, j–) // начиная с первых разрядов складываем числа
{
summa.push_front((big1.vect.at(i) + big2.vect.at(j) + temp)%10);
if ((big1.vect.at(i) + big2.vect.at(j) + temp) >= 10) temp = 1; else temp = 0; // прибавляем 1 наследующемшаге, еслисуммабольше 10
metka = i;
}
for (int i = metka-1; i >= 0; i–) // начиная с позиции метки добиваем цифрами из большего числа, учитывая возможное прибавление 1
{
summa.push_front((big1.vect.at(i)+temp)%10);
if ((big1.vect.at(i) + temp) == 10) temp = 1; else temp = 0;
}
if (temp == 1) summa.push_front(1); // срабатывает в случае когда увеличивается разряд, например 99+1=100
}
else
{
for (int i = big2.vect.size() – 1, j = big1.vect.size() – 1; j >=0; i–, j–)
{
summa.push_front((big2.vect.at(i) + big1.vect.at(j) + temp)%10);
if ((big2.vect.at(i) + big1.vect.at(j) + temp) >= 10) temp = 1; else temp = 0;
metka = i;
}
for (int i = metka-1; i >= 0; i–)
{
summa.push_front((big2.vect.at(i)+temp)%10);
if ((big2.vect.at(i) + temp) == 10) temp = 1; else temp = 0;
}
if (temp == 1) summa.push_front(1);
}
big1.vect = summa;
return big1;
}
// ________________________ Разностьбольшихчисел ________________
BigInteger rasnost (BigInteger big1, BigInteger big2)
{
if (big2.znak == '-') big2.znak = ' '; // x–y преобразуем в x+y и передаем в метод суммы
else big2.znak = '-';
if (big1.znak == big2.znak) return summa (big1, big2); // – x-y преобразуемв– (x+y) передаемметодусуммы
deque<int> rasn = deque<int>(); // сюда записывается разность
int temp = 0; // 1 для вычитания из старшего разряда
int metka = 0; // для вычисления позиции, с которой остаются разряды только одного числа
big1 = dell_null(big1); // предварительно удаляем незначащие нули из начала числа
big2 = dell_null(big2);
if (sravnenie (big1, big2)!= -1) // ставим большее число сверху в столбике
{
for (int i = big1.vect.size() – 1, j = big2.vect.size() – 1; j >=0; i–, j–)
{
if ((big1.vect.at(i) – big2.vect.at(j) + temp) >= 0) // поразрядновычитаем
{
rasn.push_front (big1.vect.at(i) – big2.vect.at(j) + temp);
temp = 0;
}
else
{
rasn.push_front (big1.vect.at(i) – big2.vect.at(j) + 10 + temp); // заимствуем 1 изстаршегоразряда
temp = -1;
}
metka = i;
}
for (int i = metka-1; i >= 0; i–) // добиваем числами оставшихся разрядов, учитывая -1
{
rasn.push_front (abs((big1.vect.at(i)+temp+10)%10));
if ((temp == -1) && (big1.vect.at(i) + temp) < 0) temp = -1; else temp = 0;
}
big1.vect = rasn;
return big1;
}
else
{
for (int i = big2.vect.size() – 1, j = big1.vect.size() – 1; j >=0; i–, j–)
{
if ((big2.vect.at(i) – big1.vect.at(j) + temp) >= 0)
{
rasn.push_front (big2.vect.at(i) – big1.vect.at(j) + temp);
temp = 0;
}
else
{
rasn.push_front (big2.vect.at(i) – big1.vect.at(j) + 10 + temp);
temp = -1;
}
metka = i;
}
for (int i = metka-1; i >= 0; i–)
{
rasn.push_front (abs((big2.vect.at(i)+temp+10)%10));
if ((temp == -1) && (big2.vect.at(i) + temp) < 0) temp = -1; else temp = 0;
}
big2.vect = rasn;
return big2;
}
}
// _______________________ Произведениебольшихчисел _____________
BigInteger proisvedenie (BigInteger big1, BigInteger big2)
{
BigInteger proisv;
proisv.vect.push_back(0);
BigInteger reserv;
BigInteger reserv2;
for (int i = big1.vect.size() – 1, count = 0; i >= 0; i –, count++)
{
if (big1.vect.at(i) == 0) {} // умножениена 0
else
if (big1.vect.at(i) == 1) // умножение на 1, просто прибавляем число с «добитыми» нулями
{
reserv2.vect = big2.vect;
for (int k = 0; k < count; k++) // добиваем нулями в зависимости от разряда умножения
reserv2.vect.push_back(0);
proisv = summa (reserv2, proisv);
}
else
{
int temp = 0;
for (int k = 0; k < count; k++) // добиваемнулями
reserv.vect.push_front(0);
for (int j = big2.vect.size() – 1; j >=0; j–) // умножаемпервоечислона«цифру» изразрядаучитывая temp
{
reserv.vect.push_front((big1.vect.at(i)*big2.vect.at(j) + temp)%10);
if ((big1.vect.at(i)*big2.vect.at(j) + temp) >=10) temp = (big1.vect.at(i)*big2.vect.at(j) + temp)/10; else temp = 0;
}
if (temp!=0) reserv.vect.push_front(temp); // приувеличенииразрядовчисла
proisv = summa (reserv, proisv); // складываем предыдущие результаты
reserv.vect.clear();
}
}
if (big1.znak!= big2.znak)
proisv.znak = '-';
return proisv;
}
// __________________ Возведение в степень большого числа _________
BigInteger stepen (BigInteger big, int steps)
{
BigInteger step;
//deque<int> step = deque<int>();
step.vect = big.vect; // постоянный множитель
for (int i = 1; i < steps; i++) // числошаговравноестепени
big = proisvedenie (big, step);
if (steps% 2 == 0)
big.znak = ' ';
return big;
}
// __________________ Факториал большого числа ____________________
BigInteger faktorial (BigInteger big)
{
big.znak = ' ';
BigInteger fak;
fak.vect.push_back(1);
BigInteger edinica;
edinica.vect.push_back(1); // дляуменьшенияна 1
{
while (big.vect.size()!= 0 && big.vect.at(0)!= 0) // пока число не стало равным 0
{
fak = proisvedenie (big, fak);
big = rasnost (big, edinica);
big = dell_null(big);
fak = dell_null(fak);
}
}
return fak;
}
// __________________ Деление больших чисел _______________________
BigInteger delenie (BigInteger delimoe, BigInteger delitel)
{
BigInteger chastnoe;
BigInteger ostatok;
BigInteger reserv2;
BigInteger reserv3;
reserv2.vect = delitel.vect;
for (int i = 0; i < (int) delimoe.vect.size(); i++)
{
ostatok = dell_null(ostatok);
ostatok.vect.push_back (delimoe.vect.at(i)); // промежуточныйостаток
if (sravnenie (ostatok, delitel) == -1) {chastnoe.vect.push_back(0);} // покапромежуточныйостатокбольшеделителяпишемвчастное 0
else
{
for (int j = 0; j < 10; j++) // цикл, формирующий цифры частного
{
if (sravnenie (ostatok, reserv2) == -1) // промежуточный остаток меньше делителя*j
{
chastnoe.vect.push_back(j);
ostatok = rasnost (ostatok, reserv3);
reserv2.vect = delitel.vect;
break;
}
if (sravnenie (ostatok, reserv2) == 0) // промежуточныйостатоккратныйделителю
{
chastnoe.vect.push_back (j+1);
ostatok.vect.clear();
reserv2.vect = delitel.vect;
break;
}
reserv3 = reserv2;
reserv2 = summa (reserv2, delitel); // прибавляем сам делитель, пока не станет больше остатка
}
}
} // цифры делимого заканчиваются и остаток меньше делимого, цикл завершается
if (delimoe.znak!= delitel.znak) chastnoe.znak = '-';
return chastnoe;
}
// __________________ Остаток от деления больших чисел ____________
BigInteger ostatok_delenie (BigInteger delimoe, BigInteger delitel)
{ // все как в методе delenie(), только возвращаем не частное, а остаток
BigInteger chastnoe;
BigInteger ostatok;
BigInteger reserv2;
BigInteger reserv3;
reserv2.vect = delitel.vect;
for (int i = 0; i < (int) delimoe.vect.size(); i++)
{
ostatok = dell_null(ostatok);
ostatok.vect.push_back (delimoe.vect.at(i));
if (sravnenie (ostatok, delitel) == -1) {chastnoe.vect.push_back(0);}
else
{
for (int j = 0; j < 10; j++)
{
if (sravnenie (ostatok, reserv2) == -1)
{
chastnoe.vect.push_back(j);
ostatok = rasnost (ostatok, reserv3);
reserv2.vect = delitel.vect;
break;
}
if (sravnenie (ostatok, reserv2) == 0)
{
chastnoe.vect.push_back (j+1);
ostatok.vect.clear();
reserv2.vect = delitel.vect;
break;
}
reserv3 = reserv2;
reserv2 = summa (reserv2, delitel);
}
}
}
if (ostatok.vect.size() == 0) ostatok.vect.push_back(0);
return ostatok;
}
// _________ Метод для использования выражений для вычисления _____
BigInteger vichislenie()