Курсовая по длинной арифметике

Автор работы: Пользователь скрыл имя, 25 Ноября 2011 в 18:50, курсовая работа

Краткое описание

Класс «длинной арифметики» – класс Math – предназначен для выполнения арифметических операций с очень большими числами, которые нельзя описать ни одним из числовых типов языка С++. В данном классе реализованы операции сложения, вычитания и умножения положительных целых чисел. Числа хранятся в виде символьного массива, память для которого выделяется при создании переменной. Так как память выделяется динамически, то ограничений, кроме объёма памяти, для количества символов нет, но ввод строки с консоли ограничен 1024 символами. Операции над числами выполняются столбиком.

Содержание

1. Введение. 3
2. Описание класса Math. 4
2.1. Закрытые переменные и члены класса. 4
2.2. Конструкторы класса Math. 4
2.3. Оператор присваивания. 5
2.4. Операторы вывода и ввода. 5
2.5. Оператор сложения. 6
2.6. Оператор вычитания. 7
2.7. Оператор умножения. 7
3. Текст класса Math. 8
4. Вывод. 12

Прикрепленные файлы: 1 файл

Курсовая по длинной арифметике.doc

— 78.00 Кб (Скачать документ)

   Содержание:

 

1. Введение.

   Класс «длинной арифметики» – класс Math – предназначен для выполнения арифметических операций с очень большими числами, которые нельзя описать ни одним из числовых типов языка С++. В данном классе реализованы операции сложения, вычитания и умножения положительных целых чисел. Числа хранятся в виде символьного массива, память для которого выделяется при создании переменной. Так как память выделяется динамически, то ограничений, кроме объёма памяти, для количества символов нет, но ввод строки с консоли ограничен 1024 символами. Операции над числами выполняются столбиком.

 

2. Описание класса Math.

     2.1.  Закрытые переменные и члены класса.

     Закрытыми переменными являются указатель на цифровую строку и переменная целого типа, хранящая длину строки вместе с завершающим символом '\0'.

     Также в закрытой области класса описаны  две функции: revers и strlen. Функция revers предназначена для обращения строки, чтобы удобнее было выполнять операции столбиком, так они производятся, начиная с последнего символа строки. Стандартный класс string также содержит эту функцию, но она обращает и исходную строку. Функция revers принимает указатель на строку, выделяет память, копирует строку наоборот, а затем возвращает указатель на обращённую строку.

     Функция strlen вычисляет длину строки. Она создана для того, чтобы не пользоваться стандартной функцией из библиотеки string.h. Функция принимает также указатель на строку. В теле функции организуется цикл, в котором проверяется каждый символ строки и наращивается индекс i, пока не встретится символ конца строки '\0', после чего возвращается значение переменной i.

     2.2. Конструкторы класса Math.

     Конструктор по умолчанию просто обнуляет указатель  s и длину строки n. Следующий конструктор принимает цифровую строку, выделяет необходимую память и копирует туда символьный массив. Копирующий конструктор принимает ссылку на объект Math, выделяет память и создаёт копию объекта.

     Деструктор  освобождает память, занятую строкой, при уничтожении объекта Math. Условный оператор if проверяет, не является ли указатель нулевым.

     2.3. Оператор присваивания.

     Для того чтобы иметь возможность  присваивать объекты Math друг другу, необходимо перегрузить оператор присваивания. Оператор имеет возвращаемое значение типа Math и перегружается с помощью служебного слова operator =. Возвращаемое значение при перегрузке оператора необходимо, чтобы иметь возможность многократного присваивания (s1=s2=s3). Возвращение значение происходит по ссылке, что позволяет избежать передачи через стек больших потоков данных.

     Вначале происходит проверка на самоприсваивание, где this – это указатель на текущий экземпляр класса. Затем происходит удаление старого содержимого, если оно имеется. После чего выделяется память, происходит копирование и возвращается текущий экземпляр класса.

     2.4. Операторы вывода и ввода.

     При перегрузке оператора первый операнд  должен быть экземпляром класса, но при перегрузке оператора вывода первым операндом является потоковая  переменная cout. Поэтому оператор вывода объявляется дружественным (служебное слово friend). Возвращаемым значением оператора является поток вывода, а в качестве параметров оператора будет поток вывода и экземпляр класса Math. Оба параметра передаются по ссылке. В теле оператора вывода просто выводится строка и возвращается поток

     Оператор  ввода также объявляем дружественным. Он возвращает поток ввода. В качестве параметров будут поток ввода  и экземпляр класса Math. В теле оператора определяется строковый массив из 1024 символов. Затем происходит ввод строки с консоли. Далее используется конструктор, который принимает строку, и возвращается поток.

     Возвращаемое  значение для этих операторов позволяет  агрегатное использование, например: cout<<s1<<s2<<endl;.

     2.5. Оператор сложения.

     Оператор  сложения имеет возвращаемое значение Math и в качестве параметра принимает экземпляр класса Math. В теле оператора определяются 3 переменные типа int: k,  m, j. Переменной k присваивается наибольшая длина строки. Переменная m – это сумма одинаковых разрядов, j – хранит число, которое прибавляется к следующему разряду (0 или 1), и имеет начальное значение 0. Указатели s1 и s2 типа char указывают на обращённые строки. Для строки str, которая хранит полученную сумму, выделяется память на один символ больше, чем наибольшая длина строки, т.е. k+1. Указатели p1 и p2  служат для хранения текущих разрядов чисел, а указатель ch хранит текущий разряд суммы. Для ch выделяется память с учётом признака конца строки `\0`, который добавляется при преобразовании из типа int в тип char.

     Вычисления производятся в цикле for. Количество шагов совпадает с количеством цифр в более длинной строке, т.е. k-1, т.к. длина строки хранится вместе с нулевым байтом. Указателям p1 и p2 присваиваются текущие разряды чисел, пока не будет достигнут конец строки. Числа из типа char преобразуются в тип int с помощью функции atoi, прототип которой помещён в файле включений stdlib.h. Переменной m присваивается сумма текущих разрядов чисел с учётом прибавки j. Затем если m>=10, то указателю ch с помощью функции itoa, которая также берётся из файла включений stdlib.h, присваивается значение m-10, а j принимает значение 1; иначе ch присваивается просто m, а j=0 (по правилу сложения столбиком). Значение указателя ch копируется в str. После цикла если j=1, то в str записывается единица следующим разрядом и признак конца строки, иначе просто признак конца строки. Строка с полученной суммой обращается в нормальное состояние и присваивается освобождённому указателю s1. Далее используется конструктор, принимающий строку (Math N(s1);), удаляется выделенная память и возвращается сумма N.

     2.6.    Оператор вычитания.

     Оператор  вычитания перегружается аналогично сложению. Только вначале проверяется, не являются ли числа одинаковыми, и, если это так, то возвращается нулевое  значение. А также, если на последнем шаге m=0, то это значение не записывается в строку разности и происходит выход из цикла с помощью оператора break. Переменная j здесь хранит число, вычитаемое из следующего разряда.

     2.7. Оператор умножения.

     В операторе умножения переменные a и b хранят длины соответственно наименьшей и наибольшей строк. Памяти под строку, которая хранит промежуточный результат умножения, выделяется 2*k–1. Указатель s1 показывает на обращённую наибольшую строку, а s2 – на наименьшую.

     В первом цикле по x  указателю p2 присваивается первый символ меньшей строки. Затем происходит сдвиг разрядов в зависимости от шага цикла (добавление нулей). В цикле по y считается промежуточный результат умножения. Переменная j здесь вычисляется как целое от m/10 и прибавляется к следующему разряду, а в текущий разряд записывается остаток от деления. После этого промежуточный результат прибавляется к переменной типа Math N, которая имеет нулевое начальное значение. Остальное происходит по аналогии с предыдущими операторами. 

 

3. Текст класса  Math.

//Класс длинной  арифметики

     #include<iostream.h>

     #include<stdlib.h>

     class Math 

     {

     private:

           char *s; //указатель на строку

           int n;  //длина сткрои

           static char *revers(char *str) //функция обращения строки

           {

                 int k=strlen(str);

                 char *p=new char[k+1];

                 for(int i=0;i<k;i++)

                       p[k-i-1]=str[i];

                 p[k]='\0';

                 return p;

           }

           static int strlen(char *str)//функция определения длины строки

           {

                 for(int i=0;str[i];i++);

                 return i;

           }

     public:

           Math(): s(0), n(0){};//Конструктор по умолчанию

           Math(char *str)   //Конструктор принимает строку текста

           {

                 n=strlen(str)+1;

                 s=new char[n];

                 for(int i=0;i<n;i++) s[i]=str[i];

           }

           //Копирующий конструктор  принимает экземпляр класса Math

           Math(Math& M)

           {

                 n=M.n;

                 s=new char[n];

                 for(int i=0;i<n;i++) s[i]=M.s[i];

           }

           //Деструктор освобождает память занятую текстом

           virtual ~Math() { if (s) delete[] s;}

           Math& operator = (Math& M)

           {

                 if (&M==this) return *this; //проверка на самоприсваивание

                 if (s) delete[] s; //удаление старого содержимого

                 n=M.n;

                 s=new char[n]; //выделение памяти

                 for(int i=0;i<n;i++) s[i]=M.s[i];//копирование

                 return *this;

           }

           //оператор вывода

           friend ostream& operator << (ostream& out, Math& M)

           {

                 out<<M.s;

                 return out;

           }

           //оператор ввода

           friend istream& operator >> (istream& in, Math& M)

           {

                 char str[1024];

                 in>>str;

                 M=Math(str);

                 return in;

           }

           //оператор сложения

           Math operator + (Math& M)

            

                 int k, m, j=0;

                 k=(n>M.n)? n:M.n;

                 char *s1, *s2, *str=new char[k+1];

                 char *p1=new char,*p2=new char,*ch=new char[2]; 

                 s1=revers(s);

                 s2=revers(M.s);

                 for(int i=0;i<k-1;i++)

                 

                       if (i<n) *p1=s1[i];

                       if (i<M.n) *p2=s2[i];

                       m=atoi(p1)+atoi(p2)+j;

          if (m>=10)  itoa(m-10,ch,10), j=1;

                       else itoa(m,ch,10), j=0;

                       str[i]=*ch;

                 }           

                 if (j==1) itoa(j,ch,10), str[i++]=*ch, str[i]='\0';

                 else str[i]='\0';

                 delete[] s1;

                 s1=revers(str);

                 Math N(s1);

                 delete[] s1;//освобождение памяти

                 delete[] s2;

                 delete[] ch;

                 delete[] str;

                 delete p1; 

                 delete p2;

                 return N;

           }

           //оператор вычитания

           Math operator - (Math& M)

           

                 for(int i=0;i<n;i++)

                 {

                       if(n!=M.n) break;

                       if(s[i]!=M.s[i]) break;

                       if(i==n-1) return Math("0");

                 }

                 int k, m, j=0;

                 k=(n>M.n)? n:M.n;

                 char *s1, *s2, *str=new char[k];

                 char *p1=new char,*p2=new char,*ch=new char[2]; 

                 s1=revers(s);

                 s2=revers(M.s);

                 for(i=0;i<k-1;i++)

                 

                       if (i<n) *p1=s1[i];

                       if (i<M.n) *p2=s2[i];

                       m=atoi(p1)-atoi(p2)-j;

Информация о работе Курсовая по длинной арифметике