Министерство образования и науки Российской Федерации
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ
ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ
«ОРЕНБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ»
Математический факультет
Кафедра компьютерной безопасности и математического обеспечения информационных систем
по дисциплине «Информатика и программирование»
Проектирование и разработка обучающей программы по переводу между римской и арабской системами счисления
ГОУ ОГУ 010503.63.6013.064О
Руководитель
_______________ Полежаев П.Н.
“_____”________________2013г.
Исполнитель
студентка гр. 12МОАИС(б)ТП
_________________Соснина П.С.
“_____”________________2013г.
Оренбург 2013
Содержание
Введение. 3
1 Техническое задание. 4
2 Выбор методов, способов и средств реализации. 5
3 Теоретические сведения. 6
4 Описание алгоритмов и основных файлов программы.. 7
4.1 Описание основных алгоритмов. 7
4.2 Файлы проекта и их основное назначение. 8
4.3 Описание основных модулей программ. 8
4.3.1 Модуль mainwindow.cpp главного окна. 8
5 Руководство пользователя. 10
5.1 Интерфейс и функциональность программы.. 10
Заключение. 13
Список использованных источников. 14
Приложение А.. 15
Текст программы.. 15
Введение
В повседневной жизни мы каждый день имеем дело с цифрами. Эта наука заинтересовала человечество еще очень давно. Научно доказано, что цифры существуют не одну тысячу лет. Первое подобие цифр датируется пятым тысячелетием до н. э. Уже тогда человек, оперируя палочками, мог вести простейшие подсчеты. Но само понятие отвлеченного числа отсутствовало, число было привязано к тем или иным конкретным объектам. Отвлеченное понятие натурального числа появляется вместе с развитием письменности.
С появлением потребности в измерениях появился и «эталон» единицы измерения, который брали за основу во всех вычислениях. Уже тогда появилась неоднозначность, ведь для разных измерений нужны разные эталоны. Тогда и условились брать за эталон десятичную систему счисления, то есть арабскую. На самом деле арабские цифры придумали не арабы – цифры пришли к нам из Индии. Заслуга арабов была в том, что они переняли из Индии форму записи чисел, позже эта форма распространилась через север Африки и Испанию в Европу.
Под системой счисления понимают способ записи чисел. Системы счисления, существовавшие ранее и ныне существующие, принято делить на позиционные и непозиционные. Наиболее совершенными считаются позиционные системы счисления, т.е. системы, в которых «вес» каждой цифры в числе зависит от ее позиции в последовательности числа. В непозиционных же каждой цифре поставлена в соответствие величина, не зависящая от положения в числе.
Перевод из представителей непозиционной системы в позиционную часто вызывает сложности у учащихся, поэтому создание обучающей программы по переводу чисел из непозиционных систем счисления в позиционные и наоборот должно помочь пользователям в усвоении материала и закреплении полученных знаний.
Во всем этом заключается актуальность данной работы.
Цель данной курсовой работы является создание обучающей программы по переводу чисел из непозиционной системы счисления (римской) в позиционную (арабскую) и обратно, которая бы способствовала лучшему усвоению материала.
1 Техническое задание
Написать программу по переводу числа из римской системы счисления в арабскую систему счисления и обратно.
Исходное задание:
- должна быть реализована программа, обучающая пользователей переводу чисел между системами счисления;
- пользователь должен самостоятельно вводить исходные данные и выбирать исходную и результативную системы счисления;
- необходимо учесть случаи некорректного ввода исходных данных пользователем и исключить выход ответа за границы допустимого диапазона;
- справочная информация предоставляется к каждому вычисляемому объекту;
- должна быть реализована возможность работы с результатом вычисления.
2 Выбор методов, способов и средств реализации
В соответствии с исходным заданием было решено хранить справочную информацию в виде текстовых файлов (файлы с расширением .txt). Файл содержит краткую теоретическую справку по переводу чисел из одной системы счисления в другую и конкретные примеры.
Входные данные представляют собой целое число или буквенную запись римских символов, считываемое из QLineEdit. Результат вычислений выводится также с помощью QLineEdit, а теоретическая справка отображается в QPlainTextEdit.
Программа реализует функции:
- перевода введенного числа из римской системы счисления в арабскую и обратно;
- отображения полученного результата в отдельном поле;
- вывода справочной информации для каждого вычисления;
- работы с результатом.
Для проектирования программ было решено пользоваться методами объектно-ориентированного программирования (ООП), как наиболее удобными для проектирования больших программных комплексов с возможностью расширения их в будущем, из-за большой гибкости в модификации и возможности оперирования со структурами данных, как с некоторыми абстрактными объектами. В качестве среды программирования была выбрана QTCreator с языком программирования C++. Данная система программирования предоставляет большие возможности при проектировании интерфейсной части приложения под операционную систему Windows, множество готовых, стандартных компонентов – элементов оконного приложения, большие удобства при кодировании и отладке программы, удобства при использовании ООП. По перечисленным выше причинам она и была выбрана как средство реализации данной работы.
3 Теоретические сведения
Римская система нумерации с помощью букв была распространена в Европе на протяжении двух тысяч лет. Только в позднем средневековье ее сменила более удобная для вычислений десятичная система цифр, заимствованная у арабов. Но, до сих пор римскими цифрами обозначаются даты на монументах, время на часах и (в англо-американской типографической традиции) страницы книжных предисловий. Кроме того, в русском языке римскими цифрами принято обозначать порядковые числительные.
Для обозначения чисел применялось 7 букв латинского алфавита: N=0, I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000. Промежуточные числа образовывались путем прибавления нескольких букв справа или слева. Таким образом, число 24 изображалось как XXIV. Горизонтальная линия над символом означала умножение на тысячу. Для правильной записи больших чисел римскими цифрами необходимо сначала записать число тысяч, затем сотен, затем десятков и, наконец, единиц.При этом некоторые из цифр (I, X, C, M) могут повторяться, но не более трёх раз; таким образом, с их помощью можно записать любое целое число не более 3999.
Натуральные числа записываются при помощи повторения этих цифр. При этом, если большая цифра стоит перед меньшей, то они складываются (принцип сложения), если же меньшая - перед большей, то меньшая вычитается из большей (принцип вычитания). Последнее правило применяется только во избежание четырёхкратного повторения одной и той же цифры. Например, I, Х, С ставятся соответственно перед Х, С, М для обозначения 9, 90, 900 или перед V, L, D для обозначения 4, 40, 400. Например, VI = 5+1 = 6, IV = 5 - 1 = 4 (вместо IIII). XIX = 10 + 10 - 1 = 19 (вместо XVIIII), XL = 50 - 10 =40 (вместо XXXX), XXXIII = 10 + 10 + 10 + 1 + 1 + 1 = 33 и т.д.
Выполнение арифметических действий над многозначными числами в этой записи весьма неудобно. Система Римских цифр настоящее время не применяется, за исключением, в отдельных случаях, обозначения веков (XV век и т.д.), годов н. э. (MCMLXXVII т. д.) и месяцев при указании дат (например, 1. V.1975), порядковых числительных.
Арабские цифры — традиционное название набора из десяти знаков: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9; ныне использующегося в большинстве стран для записи чисел в десятичной системе счисления. В этой системе счисления «вес» цифры определяется её положением. Так, 5 в числе 15 означает всего лишь пятерку, а в числе 2523 – пять сотен (ведь 2523 – это 2 раза по тысяче, 5 раз по сто, 2 раза по десять и 3).
Эта идея столь же гениальна, как укрощение огня и изобретение колеса. Не будь её, нам по старинке пришлось бы, умножая 27 на 115, пересчитывать XXVII на CXV. Без этой столь же простой, сколь и гениальной идеи не было бы ни современной физики, ни химии, люди не совершали бы полеты в космос и не была бы изобретена атомная бомба.
Подлинное преимущество арабских цифр в сравнении с римскими не в их написании, а в сверх удобном изобретении – позиционной системе счисления.
4 Описание алгоритмов и основных файлов программы
3.1 Описание основных алгоритмов
В программе используются два алгоритма:
1 Перевод из римской системы в арабскую:
1.1 Пока строка с римским числом непустая, ищем наибольшее римское число в начале строки:
- пробегаемся по словарю и ищем наибольшее подходящее слово;
- если одиночный символ встречается четырежды генерируем ошибку;
- если результат не найден, генерируем исключение;
- возвращаем результат;
- если предыдущее непустое (уже нашли хотя бы одно число);
- если предыдущее было меньше генерируем ошибку неправильного формата;
- если предыдущее было меньше десяти, тенерируем ошибку неправильного формата;
1.2 Найденное число переводим в арабскую и добавляем к результату:
- если результат больше 3999 генерируем ошибку;
- если результат равен нулю , то генерируем ошибку неправильного формата данных;
1.3 Выводим результат.
2 Перевод из арабской системы в римскую:
- если введена пустая строка, генерируем исключение пустой стро - если введены не цифры, то генерируем ошибку неправильного формата данных
- если введено число больше 3999, то генерируем ошибку неправильного фомата данных;
- пока строка с арабским числом непустая;
- пробегаемся по словарю и ищем наибольший разряд;
- отнимаем его от арабского числа и записываем в римское;
- продолжаем до тех пор пока не рассмотрим все разряды до наименьшего;
- выводим результат.
3.2 Файлы проекта и их основное назначение
О составе проекта программы можно узнать из Таблицы 1:
Таблица 1 – Основные файлы проекта программы
Имя файла |
Содержимое и назначение |
Rome.pro |
Файл проекта программы |
Main.cpp |
Модуль главной формы проекта |
mainwindow.cpp |
Модуль, содержащий реализацию пользовательского интерфейса программы |
mainwindow.h |
Заголовочный файл модуля графического интерфейса |
mainwindow.ui |
Основной модуль, содержащий графический интерфейс программы |
convert.cpp |
Модуль конвертации чисел |
3.3 Описание основных модулей программ
Кратко опишем содержание основных модулей программ, основные методы и поля классов, отвечающие за функциональность программ, и принципы их работы. Полное описание можно найти в текстах программ в приложении А.
4.3.1 Модуль mainwindow.cpp главного окна
Данный модуль содержит класс QMainWindow, основные поля которого отражены в таблице 2, а методы в таблице 3.
Таблица 2 – Основные поля класса QMainWindow
Поля |
Назначение |
QLineEdit*leNumber; |
Однострочное текстовое поле для ввода исходных данных с клавиатуры. |
QLineEdit *leResult; |
Однострочное текстовое поле для вывода результата. |
QPushButton*pbArab ; |
Кнопка для передачи сигнала перевода в арабскую систему счисления. |
QPlainTextEdit*pteHelp; |
Многострочное текстовое поле с поддержкой текстовых файлов для отображения справочной информации. |
QPushButton*pbRoman; |
Кнопка для передачи сигнала перевода в римскую систему счисления. |
QPushButton*pbSave; |
Кнопка для передачи сигнала продолжения работы с результатом. |
QPushButton*pbLoad; |
Кнопка для передачи сигнала для загрузки сохраненного результата. |
Таблица 3 – Основные методы класса формы MainWindow
Метод |
Назначение |
void ThrowEmptyStringError(); |
Функция обработки исключения типа ввода пустой строки для римских чисел. |
void ThrowEmptyStringErrorArab(); |
Функция обработки исключения типа ввода пустой строки для арабских чисел. |
void ThrowBadFormatError(const QString& val); |
Функция обработки исключения типа неправильный формат введенных данных для римских чисел. |
void ThrowOutOfRangeOrBadFormatError(const QString& val); |
Функция обработки исключения типа выхода за границу массива или неправильного формата введенных данных. |
void ThrowOutOfRangeOrBadFormatErrorArab(const QString& val); |
Функция обработки исключения типа выхода за границу массива или неправильного формата введенных данных для арабских. |
void InitTables(); |
Инициализирует словарь перевода из римских в арабские. |
void InitTablesArab(); |
Инициализирует словарь перевода из арабских в римские. |
QString RomanToArab(const QString Roman) |
Перевод римских чисел в арабские. |
QString ArabToRoman(QString Roman) |
Перевод арабских чисел в римские. |
QString GetFirstRoman(const QString& Roman) |
Возвращает первое распознанное число или генерирует исключение. |
4 Руководство пользователя
4.1 Интерфейс и функциональность программы
При запуске программы на экране появляется окно, изображенное на рисунке 1.
Рисунок 1 – Главное окно программы
Программа работает только с числами от 0 до 3999, а также латинскими буквами (I, V, X, L, C, D, M ). В случае, если пользователь введет значение, не удовлетворяющее заданным условиям или же результирующее число будет выходить за границы диапазона, программа сообщит пользователю об ошибке. Примеры таких ошибок можно увидеть на рисунках 2, 3.
Рисунок 2 – Сообщение об ошибке, в случае, когда пользователь вводит некорректные для вычисления значения.
Рисунок 3 – Сообщение об ошибке, в случае выхода результата за границы диапазона.
Если данные введены корректно, сразу после нажатия кнопки «Вычислить» на экране пользователю будет показан результат и теоретические сведения о данном типе перевода, изображенные на рисунке 4.
Рисунок 4 – Результат работы программы
Если пользователь хочет продолжить работу с полученным результатом, необходимо нажать на кнопку «Save». В результате нажатия значение результата переносится во входную строку, а значение панели выбора изменяется на противоположное. Пример работы программы изображен на рисунке 5.
Рисунок 5 – Демонстрация нажатия кнопки «Save»
Если пользователь хочет загрузить сохраненный результат, необходимо нажать на кнопку «Load». Пример работы программы изображен на рисунке 6.
Рисунок 6 –Демонстрация работы кнопки «Load»
Заключение
Разработанная программа позволяет производить перевод чисел из непозиционной римской системы счисления в позиционную арабскую и наоборот.
При описании постановки задачи приведена цель курсовой работы, характеристика исходных данных и окончательных результатов вычислений, приведены основные особенности решаемой задачи. Сформулированы требования к программе, выполнен выбор среды разработки и языка программирования.
При описании технической части (выбор методов, способов и средств реализации) даны краткие пояснения виджетов среды разработки, методов, используемых в данной программе.
Данная программа может использоваться не только как конвертер из непозиционной системы счисления в позиционную и наоборот, но и как учебное пособие, позволяющее легко и быстро овладеть основными навыками перевода чисел между системами счисления.
Полученная в результате выполнения курсовой работы программа позволит увеличить скорость расчетов по сравнению с ручными расчетами, а также повысить точность и надежность вычислений.
Список использованных источников
- Павловская, Т.А. Программирование на языке высокого уровня. – СПб.: Питер, 2008. – 468 с.
- Шлее, М. QT Профессиональное программирование на С++. – СПб.: БХВ-Петербург, 2007. – 912 с.
- Материалы сайта http://ru.wikipedia.org.
- Материалы сайта http://zablugdeniyam-net.ru.
Приложение А
(обязательное)
Текст программы
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pbLoad_clicked();
void on_pbSave_clicked();
void on_pbArab_clicked();
void on_pbRoman_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
convert.cpp
#include <QString>
#include <QMap>
using namespace std;
///////////////////////////////////////////////////////////////////////////
void ThrowEmptyStringError()
{
throw QString("Roman value is empty string.");
}
void ThrowEmptyStringErrorArab()
{
throw QString("Roman value is empty string.");
}
void ThrowBadFormatError(const QString& val)
{
throw "The \"" + val + "\" has incorrect Roman number format.";
}
void ThrowOutOfRangeOrBadFormatError(const QString& val)
{
throw "The \"" + val + "\" is greater than 3999 or has incorrect Roman number format.";
}
void ThrowOutOfRangeOrBadFormatErrorArab(const QString& val)
{
throw "The \"" + val + "\" is greater than 3999 or has incorrect Arab number format.";
}
////////////////////////////////////////////////////////////////////////////
QMap<QString, int> g_table;
void InitTables()
{
g_table["I"] = 1;
g_table["II"] = 2;
g_table["III"] = 3;
g_table["IV"] = 4;
g_table["V"] = 5;
g_table["VI"] = 6;
g_table["VII"] = 7;
g_table["VIII"] = 8;
g_table["IX"] = 9;
g_table["X"] = 10;
g_table["XX"] = 20;
g_table["XXX"] = 30;
g_table["XL"] = 40;
g_table["L"] = 50;
g_table["XC"] = 90;
g_table["C"] = 100;
g_table["CC"] = 200;
g_table["CCC"] = 300;
g_table["CD"] = 400;
g_table["D"] = 500;
g_table["CM"] = 900;
g_table["M"] = 1000;
g_table["MM"] = 2000;
g_table["MMM"] = 3000;
}
QString GetFirstRoman(const QString& Roman)
{
// Возвращает первое распознанное число в строке Roman или генерирует исключение.
// Поиск числа идет по таблице и возвращается максимальное из всех возможных.
// Для чила IX возможные кандитаты - это I и IX. Т.к. IX > I результат будет равен IX.
// Roman = CIX, result = C
// Roman XLII, result = XL
// Roman = ABX, throws excepction
int maxArab = 0;
QString result = 0;
for (QMap<QString, int>::const_iterator it = g_table.begin(), end = g_table.end(); it != end; ++it)
{
QString currentRoman = it.key();
int currentArab = it.value();
if (Roman.startsWith(currentRoman) && currentArab > maxArab)
{
if (currentRoman.length() == 1)
{
// Если число односимвольное, проверяем, не встретилась ли комбинация вроде
// IIII, XXXX, LLLL, ...
if (Roman.startsWith(QString(4, currentRoman[0])))
ThrowBadFormatError(Roman);
}
result = currentRoman;
maxArab = currentArab;
}
}
if (result == 0)
ThrowBadFormatError(Roman);
return result;
}
QString RomanToArab(const QString Roman)
{
if (Roman.isEmpty() || Roman == "N")
return QString::number(0);
InitTables();
QString str = Roman;
int result = 0;
int prevArab = 0;
while (!str.isEmpty())
{
QString currentRoman = GetFirstRoman(str);
int currentArab = g_table[currentRoman];
if (prevArab != 0)
{
// Если мы тут, значит это не первая итерация в цикле.
// У нас есть предыдущее распознанное число.
if (prevArab < 10)
{
// числа меньше 10 всегда должны быть последними. Если уже встречалось число,
// которое меньше 10, значит что-то не так с форматом римского числа.
ThrowBadFormatError(Roman);
}
if (prevArab <= currentArab)
{
// Последующее число всегда должно быть меньше прерыдущего.
// Eсли это не так, то что-то не то с форматом римского числа.
ThrowBadFormatError(Roman);
}
}
prevArab = currentArab;
result += currentArab;
if (result > 3999)
ThrowOutOfRangeOrBadFormatError(Roman);
// Вычитание из начала str строки currentRoman.
// Например, если str == "XVII", а currentRoman == "X", то после вызова substr, переменная
// str будет равна VII. После этого цикл повторяется уже для строки str="VII"
str = str.mid(currentRoman.length());
}
return QString::number(result);
}
QMap<int, QString> h_table;
void InitTablesArab()
{
h_table[1] = "I";
h_table[2] = "II";
h_table[3] = "III";
h_table[4] = "IV";
h_table[5] = "V";
h_table[6] = "VI";
h_table[7] = "VII";
h_table[8] = "VIII";
h_table[9] = "IX";
h_table[10] = "X";
h_table[20] = "XX";
h_table[30] = "XXX";
h_table[40] = "XL";
h_table[50] = "L";
h_table[90] = "XC";
h_table[100] = "C";
h_table[200] = "CC";
h_table[300] = "CCC";
h_table[400] = "CD";
h_table[500] = "D";
h_table[900] = "CM";
h_table[1000] = "M";
h_table[2000] = "MM";
h_table[3000] = "MMM";
}
QString ArabToRoman(QString Roman)
{
if(Roman.isEmpty() || Roman == "0")
{
QString x;
x.append('N');
return x;
}
for (int i = 0; i < Roman.size(); i++)//защита от дурака
{
if (Roman[i] < 48 || Roman[i] > 57)
ThrowOutOfRangeOrBadFormatErrorArab(Roman);
}
int Arab = Roman.toInt();
Roman.clear();
if(Arab > 3999)
ThrowOutOfRangeOrBadFormatErrorArab(QString::number(Arab));
InitTablesArab();
QMap<int, QString>::const_iterator it = h_table.end();
while(Arab > 0)
{
if(Arab >= it.key())
{
Roman.append(it.value());
Arab -= it.key();
}
else
it--;
}
return Roman;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "convert.cpp"
#include <QFile>
#include <QFileDialog>
#include <QTextStream>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pbLoad_clicked()
{
QString str = QFileDialog::getOpenFileName(this, "Open file", "", "Text file (*.txt);;All files (*.*)");
if (str.isEmpty())
{
return;
}
QFile file(str);
if (file.open(QIODevice::Text | QIODevice::ReadOnly))
{
QTextStream stream(&file);
ui->pteHelp->clear();
ui->leResult->clear();
ui->leNumber->clear();
bool flag=true;
QString text = stream.readAll();
for(int i=0; i<text.length();i++)
{
if (text[i] != '0' &&text[i] != '1' &&text[i] != '2'
&&text[i] != '3' &&
text[i] != '4' &&text[i] != '5' &&text[i] != '6' &&text[i] != '7' &&
text[i] != '8' &&text[i] != '9' &&text[i] != 'N' &&text[i] != 'I' &&
text[i] != 'X' &&text[i] != 'C' &&text[i] != 'L'
&& text[i] != 'M' && text[i] != 'D' && text[i] != 'V' )
{
flag=false;
break;
}
}
if (flag)
{
ui->leNumber->setText(text);
}
else
{
QMessageBox::critical(this, "Warning!", "The has incorrect data." );
}
file.close();
}
}
void MainWindow::on_pbSave_clicked()
{
QString str = "";
if(str.isEmpty())
{
str = QFileDialog::getSaveFileName(this, "Save file", "", "Text file (*.txt);;All files (*.*)");
}
QFile file(str);
if (file.open(QIODevice::Text | QIODevice::WriteOnly))
{
QTextStream(&file) << ui->leResult->text();
file.close();
}
}
void MainWindow::on_pbArab_clicked()
{
QFile file(".\\arab.txt");
if (file.open(QIODevice::Text | QIODevice::ReadOnly))
{
QTextStream stream(&file);
ui->pteHelp->clear();
ui->pteHelp->setPlainText(stream.readAll());
file.close();
}
try
{
ui->leResult->setText(RomanToArab(ui->leNumber->text().toUpper()));
}
catch (const QString& errDescr)
{
QString x;
x.append(errDescr);
x.append("\n");
QMessageBox::critical(this, "Warning!", x);
}
}
void MainWindow::on_pbRoman_clicked()
{
QFile file(".\\roman.txt");
if (file.open(QIODevice::Text | QIODevice::ReadOnly))
{
QTextStream stream(&file);
ui->pteHelp->clear();
ui->pteHelp->setPlainText(stream.readAll());
file.close();
}
try
{
ui->leResult->setText(ArabToRoman(ui->leNumber->text()));
}
catch (const QString& errDescr)
{
QString x;
x.append(errDescr);
x.append("\n");
QMessageBox::critical(this, "Warning!", x);
}
}
Скачать: