Compare commits
	
		
			3 commits
		
	
	
		
			ab6732eded
			...
			c495b7c47f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c495b7c47f | ||
|  | f0499e0d8c | ||
|  | 7e1ad95143 | 
					 4 changed files with 440 additions and 267 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <math.h> | #include <math.h> | ||||||
|  | #include <cstdlib> | ||||||
| #include "circle.h" | #include "circle.h" | ||||||
| #include "point.h" | #include "point.h" | ||||||
| 
 | 
 | ||||||
|  | @ -25,7 +26,7 @@ void Circle::setRadius(float radius) { | ||||||
|     mRadius = radius > 0 ? radius : 0; |     mRadius = radius > 0 ? radius : 0; | ||||||
| } | } | ||||||
| float Circle::getArea() const { | float Circle::getArea() const { | ||||||
|     return mRadius * mRadius * M_PI; |     return abs(mRadius * mRadius * M_PI); | ||||||
| } | } | ||||||
| float Circle::getDistance(const Point& p) { | float Circle::getDistance(const Point& p) { | ||||||
|     return mCenter.distance(p) - mRadius;  |     return mCenter.distance(p) - mRadius;  | ||||||
|  |  | ||||||
							
								
								
									
										75
									
								
								seminar02_encapsulation/homework/code/1number/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								seminar02_encapsulation/homework/code/1number/main.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | ||||||
|  | #include <iostream> | ||||||
|  | #include <cstring> | ||||||
|  | #include <vector> | ||||||
|  | #include <algorithm> | ||||||
|  | #include "number.h" | ||||||
|  | 
 | ||||||
|  | Number fib(int n) | ||||||
|  | { | ||||||
|  |     Number a = 0;		// F0
 | ||||||
|  |     Number b = 1;		// F1
 | ||||||
|  |     for (int i = 1; i <= n; ++i) { | ||||||
|  | 	if (i % 2) { | ||||||
|  | 	    a += b; | ||||||
|  | 	} else { | ||||||
|  | 	    b += a; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |     if (n % 2) { | ||||||
|  | 	return b; | ||||||
|  |     } | ||||||
|  |     return a; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Number factorial(int n) | ||||||
|  | { | ||||||
|  |     Number result { | ||||||
|  |     1}; | ||||||
|  |     for (int i = 2; i < n + 1; ++i) { | ||||||
|  | 	result = Number(i) * result; | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void grad(Number n) | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     std::cout << "n = " << n; | ||||||
|  |     Number max = n; | ||||||
|  |     unsigned long long int steps = 0; | ||||||
|  |     while (n != Number(1)) { | ||||||
|  | 	if (n > max) { | ||||||
|  | #ifdef _DEBUG_COMP | ||||||
|  | 	    std::cout << n << " is greater than " << max << std::endl; | ||||||
|  | #endif | ||||||
|  | 	    max = n; | ||||||
|  | 	} | ||||||
|  | 	if (n.isEven()) { | ||||||
|  | 	    n.div2(); | ||||||
|  | 	} else { | ||||||
|  | 	    n = Number(3) * n + Number(1); | ||||||
|  | 	} | ||||||
|  | #ifdef _DEBUG_GRAD | ||||||
|  | 	if (steps > 100) { | ||||||
|  | 	    std::cout << "break" << std::endl; | ||||||
|  | 	    break; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 	++steps; | ||||||
|  |     } | ||||||
|  |     std::cout << " steps = " << steps << " max = " << max << std::endl; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main() | ||||||
|  | { | ||||||
|  |         std::cout << "===FIB===" << std::endl; | ||||||
|  |         std::cout << "F(1000) = " << fib(1000) << std::endl;  | ||||||
|  |         std::cout << "===FAC===" << std::endl; | ||||||
|  |         std::cout << "1000! = " << factorial(1000) << std::endl; | ||||||
|  |         std::cout << "===GRAD===" << std::endl; | ||||||
|  |         grad(Number("7")); | ||||||
|  |         grad(Number("256")); | ||||||
|  |         grad(Number("1117065")); | ||||||
|  |         grad(Number("4761963248413673697")); | ||||||
|  |         grad(Number("90560792656972947582439785608972465789628974587264056284658721771")); | ||||||
|  | } | ||||||
|  | @ -1,307 +1,341 @@ | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <cstring> |  | ||||||
| #include <iomanip> | #include <iomanip> | ||||||
| #include <vector> | #include <cstring> | ||||||
| #include <algorithm> | #include "number.h" | ||||||
| 
 | 
 | ||||||
| /*
 | Number::Number(int a) | ||||||
|     Класс Number -- класс положительных больших чисел |  | ||||||
| 
 |  | ||||||
|     Большое число будет храниться в динамическом массиве data |  | ||||||
|     Каждый элемент этого массива содержит разряд числа в 100-ричной системе счисления |  | ||||||
|     (так как base = 100) |  | ||||||
|     По сути, каждый элемент data хранит две цифры числа в десятичной записи |  | ||||||
| 
 |  | ||||||
|     Значение 100 для системы счисления выбрано как компромис между |  | ||||||
|     эффективностью и удобством написания программы. |  | ||||||
|     Если выбрать значения базы 10 - то программа будет не так эффективна по памяти |  | ||||||
|     Если выбрать значения базы 256 (максимально эффективное использование памяти для типа char), |  | ||||||
|     то алгоритм печати на экран сильно усложнится |  | ||||||
|     В качестве альтернативы, можно было выбрать базу 1e9,  |  | ||||||
|     изменив при этом тип элементов c char на int |  | ||||||
| 
 |  | ||||||
|     capacity - размер массива data |  | ||||||
|     size - сколько ячеек занимет число в массиве data |  | ||||||
|     size <= capacity |  | ||||||
| 
 |  | ||||||
|     Для удобства разряды числа хранятся в обратном порядке |  | ||||||
|     Например, число 12345678 соответствует массиву |  | ||||||
|     data = {78, 56, 34, 12} |  | ||||||
|     (это упрощает многие алгоритмы с такими числами) |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Number  |  | ||||||
| { | { | ||||||
| private: |  | ||||||
|     static const int base = 100; |  | ||||||
|     std::size_t size; |  | ||||||
|     std::size_t capacity; |  | ||||||
|     char* data; |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
| 
 |  | ||||||
|     Number(int a)  |  | ||||||
|     { |  | ||||||
| #ifdef _DEBUG_CONSTRUCTOR | #ifdef _DEBUG_CONSTRUCTOR | ||||||
|          std::cout << "(Number constructor "  << a << " -> "; |     std::cout << "(Number constructor " << a << " -> "; | ||||||
| #endif | #endif | ||||||
|         // Находим размер необходимой памяти под это число
 |     // Находим размер необходимой памяти под это число
 | ||||||
|         int temp = a; |     int temp = a; | ||||||
|         capacity = 0; |     capacity = 0; | ||||||
|         while (temp != 0)  |     while (temp != 0) { | ||||||
|         { | 	temp /= base; | ||||||
|             temp /= base; | 	capacity += 1; | ||||||
|             capacity += 1; |     } | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         // Отдельно обрабатываем случай, когда число равно 0
 |     // Отдельно обрабатываем случай, когда число равно 0
 | ||||||
|         if (capacity == 0)  |     if (capacity == 0) | ||||||
|             capacity = 1; | 	capacity = 1; | ||||||
| 
 | 
 | ||||||
|         // Выделяем память и записывем число a в массив data
 |     // Выделяем память и записывем число a в массив data
 | ||||||
|         // Например, число 12345678 представится в виде массива [78, 56, 34, 12]
 |     // Например, число 12345678 представится в виде массива [78, 56, 34, 12]
 | ||||||
| 
 | 
 | ||||||
|         data = new char[capacity]; |     data = new char[capacity]; | ||||||
| 
 | 
 | ||||||
|         for (int i = 0; i < capacity; ++i)  |     for (int i = 0; i < capacity; ++i) { | ||||||
|         { | 	data[i] = a % base; | ||||||
|             data[i] = a % base; | 	a /= base; | ||||||
|             a /= base; |     } | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         // В данном случае размер будет равен вместимости
 |     // В данном случае размер будет равен вместимости
 | ||||||
|         size = capacity; |     size = capacity; | ||||||
| #ifdef _DEBUG_CONSTRUCTOR | #ifdef _DEBUG_CONSTRUCTOR | ||||||
|         std::cout << *this << ")" << std::endl; |     std::cout << *this << ")" << std::endl; | ||||||
| #endif | #endif | ||||||
|     } | } | ||||||
|     // Конструктор по умолчанию      
 |  | ||||||
|     Number() : Number(0) {} |  | ||||||
|     // Конструктор копирования
 |  | ||||||
|     Number(const Number& n) { |  | ||||||
|             size = n.size; |  | ||||||
|             capacity = n.capacity; |  | ||||||
|             data = new char[capacity]; |  | ||||||
|             for (int i = 0; i < size; i++) { |  | ||||||
|                 data[i] = n.data[i]; |  | ||||||
|             } |  | ||||||
|     } |  | ||||||
|     Number(const char* str) { |  | ||||||
|         int len = std::strlen(str); |  | ||||||
|         size = (len + len % 2) / 2; |  | ||||||
|         capacity = size; |  | ||||||
|         data = new char[capacity]; |  | ||||||
|         char buf[2]; |  | ||||||
|         for (int i = 0; i < size; i++) { |  | ||||||
|                 buf[1] = str[len - 2 * i - 1]; |  | ||||||
|                 if (len - 2 * i - 1 > 0) { |  | ||||||
|                         buf[0] = str[len - 2 * i - 2]; |  | ||||||
|                 } |  | ||||||
|                 else { |  | ||||||
|                         buf[0] = '0'; |  | ||||||
|                 } |  | ||||||
|                 data[i] = std::stoi(buf);  |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     ~Number()  |  | ||||||
|     { |  | ||||||
|         delete [] data; |  | ||||||
|     } |  | ||||||
|     Number& operator=(const Number& right) { |  | ||||||
|             capacity = right.capacity; |  | ||||||
|             size = right.size; |  | ||||||
|             data = new char[capacity]; |  | ||||||
|             for (int i = 0; i < size; i++) { |  | ||||||
|                 data[i] = right.data[i]; |  | ||||||
|             } |  | ||||||
|             return *this; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     Number operator+(const Number& a) { | // Конструктор по умолчанию      
 | ||||||
|         Number result; | Number::Number():Number(0){} | ||||||
|         int i; |  | ||||||
|         char carry = 0; |  | ||||||
|         int max_size = size > a.size ? size : a.size; |  | ||||||
| 
 | 
 | ||||||
|         result.capacity = max_size + 1; | // Конструктор копирования
 | ||||||
|         result.data = new char[capacity]; | Number::Number(const Number & n) | ||||||
| 
 | { | ||||||
|         for (i = 0; i < max_size; ++i) { |     size = n.size; | ||||||
|             result.data[i] = (data[i] + a.data[i] + carry) % base;  |     capacity = n.capacity; | ||||||
|             carry = (data[i] + a.data[i] + carry) / base; |     data = new char[capacity]; | ||||||
|         } |     for (int i = 0; i < size; i++) { | ||||||
| 
 | 	data[i] = n.data[i]; | ||||||
|         if (carry) { |  | ||||||
|             result.data[i] = carry; |  | ||||||
|             result.size = max_size + 1; |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             result.size = max_size; |  | ||||||
|         } |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|     void operator+=(const Number& a) { |  | ||||||
|         *this = *this + a; |  | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     bool isEven() const { | Number::Number(const char *str) | ||||||
|         if (data[0] % 2) { | { | ||||||
|             return false; |     int len = std::strlen(str); | ||||||
|         } |     size = (len + len % 2) / 2; | ||||||
|         return true; |     capacity = size; | ||||||
|  |     data = new char[capacity]; | ||||||
|  |     char buf[2]; | ||||||
|  |     for (int i = 0; i < size; i++) { | ||||||
|  | 	buf[1] = str[len - 2 * i - 1]; | ||||||
|  | 	if (len - 2 * i - 1 > 0) { | ||||||
|  | 	    buf[0] = str[len - 2 * i - 2]; | ||||||
|  | 	} else { | ||||||
|  | 	    buf[0] = '0'; | ||||||
|  | 	} | ||||||
|  | 	data[i] = std::stoi(buf); | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     Number operator*(const Number& right) const { | Number::~Number() | ||||||
|  | { | ||||||
|  |     delete[]data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Number & Number::operator=(const Number & right) | ||||||
|  | { | ||||||
|  |     capacity = right.capacity; | ||||||
|  |     size = right.size; | ||||||
|  |     data = new char[capacity]; | ||||||
|  |     for (int i = 0; i < size; i++) { | ||||||
|  | 	data[i] = right.data[i]; | ||||||
|  |     } | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Number Number::operator+(Number a) | ||||||
|  | { | ||||||
|  | #ifdef _DEBUG_ADD | ||||||
|  |     std::cout << "arg1=" << a << "capacity=" << a. | ||||||
|  | 	capacity << ",size=" << a.size << std::endl; | ||||||
|  |     std::cout << "arg2=" << *this << "capacity=" << this-> | ||||||
|  | 	capacity << ",size=" << this->size << std::endl; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  |     Number result; | ||||||
|  |     Number temp; | ||||||
|  |     int i; | ||||||
|  |     int carry = 0; | ||||||
|  |     if (size < a.size) { | ||||||
|  | 	temp = *this; | ||||||
|  | 	*this = a; | ||||||
|  | 	a = temp; | ||||||
|  |     } | ||||||
|  |     result.capacity = size + 1; | ||||||
|  |     //result.data = new char[capacity];
 | ||||||
|  |     result.data = (char *) calloc(result.capacity, sizeof(char)); | ||||||
|  |     for (i = 0; i < a.size; ++i) { | ||||||
|  | 	result.data[i] = (data[i] + a.data[i] + carry) % base; | ||||||
|  | 	carry = (data[i] + a.data[i] + carry) / base; | ||||||
|  |     } | ||||||
|  |     for (; i < size; ++i) { | ||||||
|  | 	result.data[i] = (data[i] + carry) % base; | ||||||
|  | 	carry = (data[i] + carry) / base; | ||||||
|  |     } | ||||||
|  |     if (carry) { | ||||||
|  | #ifdef _DEBUG_ADD | ||||||
|  | 	std::cout << "applied carry" << std::endl; | ||||||
|  | #endif | ||||||
|  | 	result.data[i] = carry; | ||||||
|  | 	result.size = size + 1; | ||||||
|  |     } else { | ||||||
|  | 	result.size = size; | ||||||
|  |     } | ||||||
|  | #ifdef _DEBUG_ADD | ||||||
|  |     std::cout << result << " capacity=" << result. | ||||||
|  | 	capacity << ",size=" << result.size << std::endl; | ||||||
|  | #endif | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Number::operator+=(const Number & a) | ||||||
|  | { | ||||||
|  |     *this = *this + a; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Number::isEven() const | ||||||
|  | { | ||||||
|  |     if (data[0] % 2) { | ||||||
|  | 	return false; | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Number Number::operator*(const Number & right) const | ||||||
|  | { | ||||||
| #ifdef _DEBUG_MUL | #ifdef _DEBUG_MUL | ||||||
|           std::cout << "arg1=" << *this << "(capacity=" << capacity << ",size=" << size << ")" << " " << "arg2=" << right << "(capacity=" << right.capacity << ",size=" << right.size << ")"<<  std::endl; |     std:: | ||||||
|  | 	cout << "arg1=" << *this << "(capacity=" << capacity << ",size=" << | ||||||
|  | 	size << ")" << " " << "arg2=" << right << "(capacity=" << right. | ||||||
|  | 	capacity << ",size=" << right.size << ")" << std::endl; | ||||||
| #endif | #endif | ||||||
|           int i, j; |     int i, j; | ||||||
|           int temp; |     int temp; | ||||||
|           Number result; |     Number result; | ||||||
| 
 | 
 | ||||||
|           result.capacity = capacity + right.capacity; |     result.capacity = capacity + right.capacity; | ||||||
|           int *carry = (int*)std::calloc(result.capacity, sizeof(int)); |     int *carry = (int *) std::calloc(result.capacity, sizeof(int)); | ||||||
| 
 | 
 | ||||||
|           result.data = (char*)calloc(result.capacity, sizeof(char)); |     result.data = (char *) calloc(result.capacity, sizeof(char)); | ||||||
| #ifdef   _DEBUG_MUL | #ifdef   _DEBUG_MUL | ||||||
|           std::cout << "carry:[" << carry[0]; |     std::cout << "carry:[" << carry[0]; | ||||||
|           for (int k = 1; k < result.capacity; ++k) { |     for (int k = 1; k < result.capacity; ++k) { | ||||||
|             std::cout << "," << carry[k]; | 	std::cout << "," << carry[k]; | ||||||
|           } |  | ||||||
|           std::cout << "]" << std::endl; |  | ||||||
| #endif |  | ||||||
|           for (i = 0; i < size; ++i) { |  | ||||||
|                 for (j = 0; j < right.size; ++j) { |  | ||||||
| #ifdef _DEBUG_MUL |  | ||||||
|                     std::cout << i + j << ":" << static_cast<int>(result.data[i + j]) << " + " << static_cast<int>(data[i]) << " * " << static_cast<int>(right.data[j]) << " + " << carry[i+j] << std::endl; |  | ||||||
| #endif |  | ||||||
|                     temp = (result.data[i + j] + data[i] * right.data[j] + carry[i + j]); |  | ||||||
|                     result.data[i + j] = temp % base; |  | ||||||
|                     carry[i + j + 1] += temp / base; |  | ||||||
|                     carry[i + j] = 0; |  | ||||||
| 
 |  | ||||||
|                 } |  | ||||||
|           } |  | ||||||
| #ifdef _DEBUG_MUL |  | ||||||
|           std::cout << "result before applying carry:" << result << std::endl; |  | ||||||
|           std::cout << "carry:[" << carry[0]; |  | ||||||
|           for (int k = 1; k < result.capacity; ++k) { |  | ||||||
|             std::cout << "," << carry[k]; |  | ||||||
|           } |  | ||||||
|           std::cout << "]" << std::endl; |  | ||||||
| #endif |  | ||||||
|           if (carry[i + j - 1]) { |  | ||||||
|             result.data[i + j - 1] = carry[i + j - 1]; |  | ||||||
|             result.size = i + j; |  | ||||||
|             carry[i + j - 1] = 0; |  | ||||||
|           } |  | ||||||
|           else { |  | ||||||
|             result.size = i + j - 1; |  | ||||||
|           } |  | ||||||
|            |  | ||||||
| #ifdef _DEBUG_MUL |  | ||||||
|           std::cout << "before correcting capacity, result=" << result << std::endl; |  | ||||||
| #endif |  | ||||||
|           // correcting capacity
 |  | ||||||
|           /*char* temp_data = (char *)calloc(result.size, sizeof(char));
 |  | ||||||
|           for (i = 0; i < result.size; ++i) { |  | ||||||
|             temp_data[i] = result.data[i]; |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           free(result.data); |  | ||||||
|           result.capacity = result.size; |  | ||||||
|           result.data = (char*)calloc(result.size,sizeof(char)); |  | ||||||
|           for (i = 0; i < result.size; ++i) { |  | ||||||
|             result.data[i] = temp_data[i]; |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           free(temp_data);*/ |  | ||||||
|           free(carry); |  | ||||||
| #ifdef _DEBUG_MUL |  | ||||||
|           std::cout << "return value=" << result << "(capacity=" << result.capacity << ",size=" << result.size << ")" << std::endl << "======" << std::endl; |  | ||||||
| #endif |  | ||||||
|           return result; |  | ||||||
|     } |     } | ||||||
|     void operator*=(const Number& a) { |     std::cout << "]" << std::endl; | ||||||
|         *this = *this * a; | #endif | ||||||
|  |     for (i = 0; i < size; ++i) { | ||||||
|  | 	for (j = 0; j < right.size; ++j) { | ||||||
|  | #ifdef _DEBUG_MUL | ||||||
|  | 	    std::cout << i + j << ":" << static_cast < | ||||||
|  | 		int >(result.data[i + j]) << " + " << static_cast < | ||||||
|  | 		int >(data[i]) << " * " << static_cast < | ||||||
|  | 		int >(right.data[j]) << " + " << carry[i + j] << std::endl; | ||||||
|  | #endif | ||||||
|  | 	    temp = | ||||||
|  | 		(result.data[i + j] + data[i] * right.data[j] + | ||||||
|  | 		 carry[i + j]); | ||||||
|  | 	    result.data[i + j] = temp % base; | ||||||
|  | 	    carry[i + j + 1] += temp / base; | ||||||
|  | 	    carry[i + j] = 0; | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  | #ifdef _DEBUG_MUL | ||||||
|  |     std::cout << "result before applying carry:" << result << std::endl; | ||||||
|  |     std::cout << "carry:[" << carry[0]; | ||||||
|  |     for (int k = 1; k < result.capacity; ++k) { | ||||||
|  | 	std::cout << "," << carry[k]; | ||||||
|  |     } | ||||||
|  |     std::cout << "]" << std::endl; | ||||||
|  | #endif | ||||||
|  |     if (carry[i + j - 1]) { | ||||||
|  | 	result.data[i + j - 1] = carry[i + j - 1]; | ||||||
|  | 	result.size = i + j; | ||||||
|  |     } else { | ||||||
|  | 	result.size = i + j - 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     friend std::ostream& operator<<(std::ostream& stream, const Number& right); | #ifdef _DEBUG_MUL | ||||||
|     friend int main(); |     std::cout << "before correcting capacity, result=" << result << std:: | ||||||
|     friend Number factorial(int n); | 	endl; | ||||||
| }; | #endif | ||||||
|  |     // correcting capacity
 | ||||||
|  |     /*char* temp_data = (char *)calloc(result.size, sizeof(char));
 | ||||||
|  |        for (i = 0; i < result.size; ++i) { | ||||||
|  |        temp_data[i] = result.data[i]; | ||||||
|  |        } | ||||||
|  | 
 | ||||||
|  |        free(result.data); | ||||||
|  |        result.capacity = result.size; | ||||||
|  |        result.data = (char*)calloc(result.size,sizeof(char)); | ||||||
|  |        for (i = 0; i < result.size; ++i) { | ||||||
|  |        result.data[i] = temp_data[i]; | ||||||
|  |        } | ||||||
|  | 
 | ||||||
|  |        free(temp_data); */ | ||||||
|  |     free(carry); | ||||||
|  | #ifdef _DEBUG_MUL | ||||||
|  |     std::cout << "return value=" << result << "(capacity=" << result. | ||||||
|  | 	capacity << ",size=" << result. | ||||||
|  | 	size << ")" << std::endl << "======" << std::endl; | ||||||
|  | #endif | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Number::operator*=(const Number & a) | ||||||
|  | { | ||||||
|  |     *this = *this * a; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Number::operator==(const Number & a) const | ||||||
|  | { | ||||||
|  |     if (size != a.size) { | ||||||
|  | 	return false; | ||||||
|  |     } | ||||||
|  |     for (int i = 0; i < size; ++i) { | ||||||
|  | 	if (data[i] != a.data[i]) { | ||||||
|  | 	    return false; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Number::operator!=(const Number & a) const | ||||||
|  | { | ||||||
|  |     return not(*this == a); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Number::operator>(const Number & a) const | ||||||
|  | { | ||||||
|  | #ifdef _DEBUG_COMP | ||||||
|  |     std:: | ||||||
|  | 	cout << "comp " << *this << "(size=" << size << ") and " << a << | ||||||
|  | 	"(size=" << a.size << ")" << std::endl; | ||||||
|  | #endif | ||||||
|  |     if (size > a.size) { | ||||||
|  | #ifdef _DEBUG_COMP | ||||||
|  | 	std::cout << "size > a.size => true" << std::endl; | ||||||
|  | #endif | ||||||
|  | 	return true; | ||||||
|  |     } | ||||||
|  |     if (size < a.size) { | ||||||
|  | #ifdef _DEBUG_COMP | ||||||
|  | 	std::cout << "size < a.size => false" << std::endl; | ||||||
|  | #endif | ||||||
|  | 	return false; | ||||||
|  |     } | ||||||
|  |     for (int i = size - 1; i >= 0; --i) { | ||||||
|  | 	if (data[i] > a.data[i]) { | ||||||
|  | 	    return true; | ||||||
|  | #ifdef _DEBUG_COMP | ||||||
|  | 	    std::cout << static_cast < | ||||||
|  | 		int >(data[i]) << ">" << static_cast < | ||||||
|  | 		int >(a.data[i]) << std::endl; | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  | 	if (data[i] < a.data[i]) { | ||||||
|  | #ifdef _DEBUG_COMP | ||||||
|  | 	    std::cout << static_cast < | ||||||
|  | 		int >(data[i]) << "<" << static_cast < | ||||||
|  | 		int >(a.data[i]) << std::endl; | ||||||
|  | #endif | ||||||
|  | 	    return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | #ifdef _DEBUG_COMP | ||||||
|  |     std::cout << "using final false" << std::endl; | ||||||
|  | #endif | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Number::operator<(const Number & a) const | ||||||
|  | { | ||||||
|  |     return not(*this > a) and(*this != a); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Number::div2() | ||||||
|  | { | ||||||
|  | #ifdef _DEBUG_DIV2 | ||||||
|  |     std::cout << "n = " << *this << std::endl; | ||||||
|  | #endif | ||||||
|  |     int carry = 0; | ||||||
|  |     int temp; | ||||||
|  |     for (int i = size - 1; i >= 0; --i) { | ||||||
|  | 	temp = data[i] + carry * base; | ||||||
|  | 	data[i] = temp / 2; | ||||||
|  | 	carry = temp % 2; | ||||||
|  |     } | ||||||
|  |     if (data[size - 1] == 0) { | ||||||
|  | 	--size; | ||||||
|  |     } | ||||||
|  | #ifdef _DEBUG_DIV2 | ||||||
|  |     std::cout << "unstripped result " << *this << std::endl; | ||||||
|  | #endif | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | std::ostream & operator<<(std::ostream & stream, const Number & right) | ||||||
| std::ostream& operator<<(std::ostream& stream, const Number& right) |  | ||||||
| { | { | ||||||
| #ifdef _DEBUG_COUT | #ifdef _DEBUG_COUT | ||||||
|     stream << "["; |     stream << "["; | ||||||
|     for (std::size_t i = 0; i < right.size; ++i) { |     for (std::size_t i = 0; i < right.size; ++i) { | ||||||
|         stream << static_cast<int>(right.data[right.size - 2 - i]) << ","; | 	stream << static_cast < | ||||||
|  | 	    int >(right.data[right.size - 2 - i]) << ","; | ||||||
|     } |     } | ||||||
|     stream << "]"; |     stream << "]"; | ||||||
| #else | #else | ||||||
|      // Печатаем самый большой разряд
 |     // Печатаем самый большой разряд
 | ||||||
|     stream << (int)right.data[right.size - 1]; |     stream << (int) right.data[right.size - 1]; | ||||||
| 
 | 
 | ||||||
|     // Печатаем остальные разряды с заполнением нулями до 2-х цифр
 |     // Печатаем остальные разряды с заполнением нулями до 2-х цифр
 | ||||||
|     // setfill и setw это то же самое, что и в языке C спецификатор %02d
 |     // setfill и setw это то же самое, что и в языке C спецификатор %02d
 | ||||||
|     for (std::size_t i = 0; i < right.size - 1; ++i) |     for (std::size_t i = 0; i < right.size - 1; ++i) | ||||||
|         stream << std::setfill('0') << std::setw(2) << (int)right.data[right.size - 2 - i]; | 	stream << std::setfill('0') << std::setw(2) << (int) right. | ||||||
|  | 	    data[right.size - 2 - i]; | ||||||
| #endif | #endif | ||||||
|     return stream; |     return stream; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| Number fib(int n) { |  | ||||||
|     Number a = 0; // F0
 |  | ||||||
|     Number b = 1; // F1
 |  | ||||||
|     for (int i = 1; i <=n; ++i) { |  | ||||||
|         if (i % 2) { |  | ||||||
|             a += b; |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             b += a; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     if (n % 2) { |  | ||||||
|         return b; |  | ||||||
|     } |  | ||||||
|     return a; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Number factorial(int n) { |  | ||||||
|     Number result{1}; |  | ||||||
|     for (int i = 2; i < n + 1; ++i) { |  | ||||||
|         result = Number(i) * result; |  | ||||||
|     } |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main()  |  | ||||||
| { |  | ||||||
|     Number x = Number("25852016738884976640000"); |  | ||||||
|     Number y = Number("24"); |  | ||||||
| 
 |  | ||||||
|     //char s[3];
 |  | ||||||
|     //Number result = "1";
 |  | ||||||
|     //for (int i = 1; i < 26; ++i) {
 |  | ||||||
|         //s = std::to_string(i);
 |  | ||||||
|         //sprintf(s, "%d", i);
 |  | ||||||
|     //    result = (Number{i} * result);
 |  | ||||||
|     //}   
 |  | ||||||
|     //x += y;
 |  | ||||||
|     //Number z = x + y;
 |  | ||||||
|     //std::cout << fib(1000) << std::endl;
 |  | ||||||
|     //x = x * Number(24)*Number{25};
 |  | ||||||
|     //y = factorial(5);
 |  | ||||||
|     //std::cout << x << " " << x.capacity << " " << x.size << std::endl;
 |  | ||||||
|     //std::cout << y << " "<< y.capacity << " " << y.size << std::endl;
 |  | ||||||
|     // 90405070506200618121707-18-13-05-18-08
 |  | ||||||
|     //std::cout << "===" << std::endl << Number(2) * Number(3) << " "<< Number(3) * Number(2) << std::endl;
 |  | ||||||
|     //std::cout << "5! = " << Number(2) * Number(3) * Number(4) * Number(5) << std::endl;
 |  | ||||||
|     std::cout << factorial(1000) << std::endl; |  | ||||||
|     //std::cout << Number("620448401733239439360000") * Number(25) << std::endl;
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										63
									
								
								seminar02_encapsulation/homework/code/1number/number.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								seminar02_encapsulation/homework/code/1number/number.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | ||||||
|  | #pragma once | ||||||
|  | /*
 | ||||||
|  |     Класс Number -- класс положительных больших чисел | ||||||
|  | 
 | ||||||
|  |     Большое число будет храниться в динамическом массиве data | ||||||
|  |     Каждый элемент этого массива содержит разряд числа в 100-ричной системе счисления | ||||||
|  |     (так как base = 100) | ||||||
|  |     По сути, каждый элемент data хранит две цифры числа в десятичной записи | ||||||
|  | 
 | ||||||
|  |     Значение 100 для системы счисления выбрано как компромис между | ||||||
|  |     эффективностью и удобством написания программы. | ||||||
|  |     Если выбрать значения базы 10 - то программа будет не так эффективна по памяти | ||||||
|  |     Если выбрать значения базы 256 (максимально эффективное использование памяти для типа char), | ||||||
|  |     то алгоритм печати на экран сильно усложнится | ||||||
|  |     В качестве альтернативы, можно было выбрать базу 1e9,  | ||||||
|  |     изменив при этом тип элементов c char на int | ||||||
|  | 
 | ||||||
|  |     capacity - размер массива data | ||||||
|  |     size - сколько ячеек занимет число в массиве data | ||||||
|  |     size <= capacity | ||||||
|  | 
 | ||||||
|  |     Для удобства разряды числа хранятся в обратном порядке | ||||||
|  |     Например, число 12345678 соответствует массиву | ||||||
|  |     data = {78, 56, 34, 12} | ||||||
|  |     (это упрощает многие алгоритмы с такими числами) | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | class Number { | ||||||
|  |   private: | ||||||
|  |     static const int base = 100; | ||||||
|  |      std::size_t size; | ||||||
|  |      std::size_t capacity; | ||||||
|  |     char *data; | ||||||
|  | 
 | ||||||
|  |   public: | ||||||
|  | 
 | ||||||
|  |      Number(int a); | ||||||
|  |      Number(); | ||||||
|  |     // Конструктор копирования
 | ||||||
|  |      Number(const Number & n); | ||||||
|  |      Number(const char *str); | ||||||
|  |     ~Number(); | ||||||
|  |      Number & operator=(const Number & right); | ||||||
|  | 
 | ||||||
|  |     Number operator+(Number a); | ||||||
|  |     void operator+=(const Number & a); | ||||||
|  | 
 | ||||||
|  |     bool isEven() const; | ||||||
|  | 
 | ||||||
|  |     Number operator*(const Number & right) const; | ||||||
|  |     void operator*=(const Number & a); | ||||||
|  | 
 | ||||||
|  |     bool operator==(const Number & a) const; | ||||||
|  |     bool operator!=(const Number & a) const; | ||||||
|  |     bool operator>(const Number & a) const; | ||||||
|  |     bool operator<(const Number & a) const; | ||||||
|  |     void div2(); | ||||||
|  | 
 | ||||||
|  |     friend std::ostream & operator<<(std::ostream & stream, | ||||||
|  | 				     const Number & right); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | std::ostream & operator<<(std::ostream & stream, const Number & right); | ||||||
		Reference in a new issue