Главная Рефераты по рекламе Рефераты по физике Рефераты по философии Рефераты по финансам Рефераты по химии Рефераты по хозяйственному праву Рефераты по цифровым устройствам Рефераты по экологическому праву Рефераты по экономико-математическому моделированию Рефераты по экономической географии Рефераты по экономической теории Рефераты по этике Рефераты по юриспруденции Рефераты по языковедению Рефераты по юридическим наукам Рефераты по истории Рефераты по компьютерным наукам Рефераты по медицинским наукам Рефераты по финансовым наукам Рефераты по управленческим наукам Психология и педагогика Промышленность производство Биология и химия Языкознание филология Издательское дело и полиграфия Рефераты по краеведению и этнографии Рефераты по религии и мифологии Рефераты по медицине Рефераты по сексологии Рефераты по информатике программированию Краткое содержание произведений |
Курсовая работа: Реализация класса больших чиселКурсовая работа: Реализация класса больших чиселПояснительная записка «Реализация класса больших чисел» Введение Постановка задачиРеализовать средствами языка С++ класс больших целых чисел. Для написания класса были выделены следующие задачи: · Организовать чтение из консоли и печать в консоль целых чисел, длина которых превышает 232 разрядов (стандартный тип long) · Реализовать выполнение арифметических операции с данными числами: o Сложение o Вычитание o Произведение o Нахождение целой части от деления o Нахождение остатка от деления o Возведение в степень Факториал
|
Порядковый номер вычисления | Время вычисления, сек |
1 | 2,446 |
2 | 2,448 |
3 | 2,426 |
4 | 2,451 |
5 | 2,441 |
6 | 2,442 |
7 | 2,442 |
8 | 2,443 |
Среднее время вычисления | 2,442 |
Таким образом, программа вычисляет факториал 1000 в среднем за 2,442 секунды.
Пожалуй, самой сложной для реализации, является операция деления и нахождение остатка от деления двух больших чисел. Методы соответствующие данным операциям были названы delenie (BigInteger, BigInteger) и ostasok_delenie (BigInteger, BigInteger) соответсвенно. В основе лежит принцип деления «столбиком». Пример работы алгоритма приведен на рисунке 8.
Рис. 8. Операция деления и нахождение остатка от деления
Ход алгоритма следующий: сравниваем делитель с делимым, прибавляя поразрядно по одной цифре к делителю в случае, если получившийся делитель меньше делимого, при этом в частное записываем 0. На рисунке 8 видно этот этап: 2<7985, в частное записываем 0, затем 21<7985, в частное записываем 0, и так далее пока не поменяется знак неравенства 21367>7985. После этого запускается цикл по нахождению следующей цифры частного. На каждом шаге делитель прибавляется на величину равную самому делителю, пока он не станет больше либо равен нашему промежуточному делимому, т.е. 21367. Шаг цикла, на котором выполнится данное условие, и будет искомой цифрой для частного. Затем вычитаем из промежуточного делимого полученное в ходе цикла число и получаем промежуточный остаток. Так как он точно меньше делителя (в связи с предыдущими условиями), добавляем к нему следующую не задействованную цифру делимого и переходим к первому шагу алгоритма. Алгоритм считается выполненным, если получается остаток, меньший делителя и не осталось ни одной незадействованной цифры делимого. В зависимости от задачи, метод возвращает либо частное, либо остаток от деления.
Для удобства пользователей был введен еще один метод 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()
{
BigInteger big1;
BigInteger big2;
string temp = «0123456789»;
string snaki = «-+*/%!^»;
string str;
cin >> str; // считываем строку и в зависимости от знака выбираем действие с числами через switch
int perekluchatel = -1;
if (str.at(0) == snaki.at(0)) big1.znak = '-';
for (int i = 0; i < (int) str.length(); i++)
{
for (int j = 0; j < 10; j++)
{
if ((perekluchatel == -1) && (str.at(i) == temp.at(j))) {big1.vect.push_back(j); break;}
if ((perekluchatel!= -1) && (str.at(i) == temp.at(j))) {big2.vect.push_back(j); break;}
}
if (perekluchatel == -1)
for (int j = 0; j < 7; j++)
{
if ((str.at(i) == snaki.at(j)) && (i!= 0))
{
perekluchatel = j;
if (perekluchatel == 5) break;
if (str.at (i+1) == snaki.at(0)) big2.znak = '-'; break;
}
}
}
cout << str << «=»;
switch(perekluchatel)
{
case 0:
{
return rasnost (big1, big2); break;
}
case 1:
{
return summa (big1, big2); break;
}
case 2:
{
return proisvedenie (big1, big2); break;
}
case 3:
{
return delenie (big1, big2); break;
}
case 4:
{
return ostatok_delenie (big1, big2); break;
}
case 5:
{
return faktorial(big1); break;
}
case 6:
{
BigInteger edinica;
edinica.vect.push_back(1);
BigInteger dvoika;
dvoika.vect.push_back(2);
BigInteger step;
step.vect = big1.vect;
BigInteger tempbig2;
tempbig2.vect = big2.vect;
big2.znak = ' ';
while (big2.vect.size()!= 0 && big2.vect.at(0)!= 1)
{
big1 = proisvedenie (big1, step);
big2 = rasnost (big2, edinica);
big2 = dell_null(big2);
}
BigInteger proverka = ostatok_delenie (tempbig2, dvoika);
if (proverka.vect.at(0) == 0)
big1.znak = ' ';
return big1;
break;
}
}
}
};
Листинг 2. Файл Main.cpp
#include <clocale>
#include «BigInteger.h» // подключаем класс больших целых чисел
void main() // функция использующая большие целые числа
{
setlocale (LC_CTYPE, «Russian»);
BigInteger bint1;
BigInteger bint2;
BigInteger summ;
BigInteger rasn;
BigInteger proisv;
BigInteger step;
BigInteger fak;
BigInteger chastnoe;
int x, y; // переключатели режима вычисления
bool flag = true;
cout << «Выберите режим вычисления:\n1 – режим выражения\n2 – режим выбора операции\n ->»;
cin >> y;
if (y == 1)
{
cout << «Введите выражение для вычисления:\n»;
while (true)
{
BigInteger resultat;
resultat = resultat.vichislenie();
resultat.vector_print(resultat);
cout << endl;
}
}
else
{
cout << «Введите первое число:»;
bint1 = bint1.chtenie();
cout << «Введите второе число:»;
bint2 = bint2.chtenie();
while (flag == true)
{
cout << «\n\nВведите номер операции: \n»;
cout << «1 – сложение чисел \n»;
cout << «2 – разность чисел \n»;
cout << «3 – умножение чисел \n»;
cout << «4 – деление чисел \n»;
cout << «5 – остаток от деления чисел \n»;
cout << «6 – возведение в степень \n»;
cout << «7 – факториал \n»;
cout << «8 – ввести новые числа\n»;
cout << «9 – выйти из программы\n»;
cout << «->»;
cin >> x;
switch(x)
{
case 1:
{
cout << «\nСумма чисел:»;
summ = summ.summa (bint1, bint2);
summ.vector_print(summ);
break;
}
case 2:
{
cout << «\nРазность чисел:»;
rasn = rasn.rasnost (bint1, bint2);
rasn.vector_print(rasn);
break;
}
case 3:
{
cout << «\nПроизведение чисел:»;
proisv = proisv.proisvedenie (bint1, bint2);
proisv.vector_print(proisv);
break;
}
case 4:
{
cout << «\nДеление чисел:»;
chastnoe = chastnoe.delenie (bint1, bint2);
chastnoe.vector_print(chastnoe);
break;
}
case 5:
{
cout << «\nОстаток от деления чисел:»;
chastnoe = chastnoe.ostatok_delenie (bint1, bint2);
chastnoe.vector_print(chastnoe);
break;
}
case 6:
{
int st;
cout << «Введите в какую степень нужно возвести первое число:»;
cin >> st;
cout << «\n» << st <<» – ая степень числа:»;
step = step.stepen (bint1, st);
step.vector_print(step);
break;
}
case 7:
{
cout << «\nФакториал первого числа:»;
fak = fak.faktorial(bint1);
fak.vector_print(fak);
break;
}
case 8:
{
bint1 = BigInteger();
cout << «\nВведите первое число:»;
bint1 = bint1.chtenie();
bint2 = BigInteger();
cout << «Введите второе число:»;
bint2 = bint2.chtenie();
break;
}
case 9:
{
flag = false;
break;
}
default:
{
cout << «\nОшибка ввода, повторите процедуру!»;