number final

master
nihonium 2 years ago
parent f0499e0d8c
commit c495b7c47f
No known key found for this signature in database
GPG Key ID: 0251623741027CFC

@ -4,74 +4,72 @@
#include <algorithm> #include <algorithm>
#include "number.h" #include "number.h"
Number fib(int n) { Number fib(int n)
Number a = 0; // F0 {
Number b = 1; // F1 Number a = 0; // F0
for (int i = 1; i <=n; ++i) { Number b = 1; // F1
if (i % 2) { for (int i = 1; i <= n; ++i) {
a += b; if (i % 2) {
} a += b;
else { } else {
b += a; b += a;
} }
} }
if (n % 2) { if (n % 2) {
return b; return b;
} }
return a; return a;
} }
Number factorial(int n) { Number factorial(int n)
Number result{1}; {
Number result {
1};
for (int i = 2; i < n + 1; ++i) { for (int i = 2; i < n + 1; ++i) {
result = Number(i) * result; result = Number(i) * result;
} }
return result; return result;
} }
void grad(Number n) { void grad(Number n)
{
std::cout << "n = " << n; std::cout << "n = " << n;
Number max = n; Number max = n;
unsigned long long int steps = 0; unsigned long long int steps = 0;
while (n != Number(1)) { while (n != Number(1)) {
if (n > max) { if (n > max) {
#ifdef _DEBUG_COMP #ifdef _DEBUG_COMP
std::cout << n << " is greater than " << max << std::endl; std::cout << n << " is greater than " << max << std::endl;
#endif #endif
max = n; max = n;
} }
if (n.isEven()) { if (n.isEven()) {
n.div2(); n.div2();
} } else {
else { n = Number(3) * n + Number(1);
n = Number(3) * n + Number(1); }
}
#ifdef _DEBUG_GRAD #ifdef _DEBUG_GRAD
if(steps > 100) { if (steps > 100) {
std::cout << "break" << std::endl; std::cout << "break" << std::endl;
break; break;
} }
#endif #endif
++steps; ++steps;
} }
std::cout << " steps = " << steps << " max = " << max << std::endl; std::cout << " steps = " << steps << " max = " << max << std::endl;
} }
int main() int main()
{ {
std::cout << fib(1000) << std::endl; std::cout << "===FIB===" << std::endl;
//x = x * Number(24)*Number{25}; std::cout << "F(1000) = " << fib(1000) << std::endl;
//y = factorial(5); std::cout << "===FAC===" << std::endl;
//std::cout << x << " " << x.capacity << " " << x.size << std::endl; std::cout << "1000! = " << factorial(1000) << std::endl;
//std::cout << y << " "<< y.capacity << " " << y.size << std::endl; std::cout << "===GRAD===" << std::endl;
//std::cout << "===" << std::endl << Number(2) * Number(3) << " "<< Number(3) * Number(2) << std::endl; grad(Number("7"));
//std::cout << "5! = " << Number(2) * Number(3) * Number(4) * Number(5) << std::endl; grad(Number("256"));
//std::cout << factorial(1000) << std::endl; grad(Number("1117065"));
//std::cout << Number("620448401733239439360000") * Number(25) << std::endl; grad(Number("4761963248413673697"));
//std::cout << (y < x) << std::endl; grad(Number("90560792656972947582439785608972465789628974587264056284658721771"));
//grad(Number("4761963248413673697"));
//grad(Number("256"));
//std::cout << Number(128) * Number(3) + Number(1) + Number(2) + Number(3) + Number(4) << std::endl;
} }

@ -3,297 +3,339 @@
#include <cstring> #include <cstring>
#include "number.h" #include "number.h"
Number::Number(int a) Number::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;
{ a /= base;
data[i] = 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() : Number(0) {} Number::Number():Number(0){}
// Конструктор копирования // Конструктор копирования
Number::Number(const Number& n) { Number::Number(const Number & n)
size = n.size; {
capacity = n.capacity; size = n.size;
data = new char[capacity]; capacity = n.capacity;
for (int i = 0; i < size; i++) { data = new char[capacity];
data[i] = n.data[i]; for (int i = 0; i < size; i++) {
} data[i] = n.data[i];
}
Number::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::~Number() }
{
delete [] data; Number::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& Number::operator=(const Number& right) { }
capacity = right.capacity;
size = right.size; Number::~Number()
data = new char[capacity]; {
for (int i = 0; i < size; i++) { delete[]data;
data[i] = right.data[i]; }
}
return *this; 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) { Number Number::operator+(Number a)
{
#ifdef _DEBUG_ADD #ifdef _DEBUG_ADD
std::cout << "arg1=" << a << "capacity=" << a.capacity << ",size="<< a.size<< std::endl; std::cout << "arg1=" << a << "capacity=" << a.
std::cout << "arg2=" << *this << "capacity=" << this->capacity << ",size="<< this->size<< std::endl; capacity << ",size=" << a.size << std::endl;
std::cout << "arg2=" << *this << "capacity=" << this->
capacity << ",size=" << this->size << std::endl;
#endif #endif
Number result; Number result;
Number temp; Number temp;
int i; int i;
int carry = 0; int carry = 0;
if (size < a.size) { if (size < a.size) {
temp = *this; temp = *this;
*this = a; *this = a;
a = temp; a = temp;
} }
result.capacity = size + 1; result.capacity = size + 1;
//result.data = new char[capacity]; //result.data = new char[capacity];
result.data = (char*)calloc(result.capacity, sizeof(char)); result.data = (char *) calloc(result.capacity, sizeof(char));
for (i = 0; i < a.size; ++i) { for (i = 0; i < a.size; ++i) {
result.data[i] = (data[i] + a.data[i] + carry) % base; result.data[i] = (data[i] + a.data[i] + carry) % base;
carry = (data[i] + a.data[i] + carry) / base; carry = (data[i] + a.data[i] + carry) / base;
} }
for (; i < size; ++i) { for (; i < size; ++i) {
result.data[i] = (data[i] + carry) % base; result.data[i] = (data[i] + carry) % base;
carry = (data[i] + carry) / base; carry = (data[i] + carry) / base;
} }
if (carry) { if (carry) {
#ifdef _DEBUG_ADD #ifdef _DEBUG_ADD
std::cout << "applied carry" << std::endl; std::cout << "applied carry" << std::endl;
#endif #endif
result.data[i] = carry; result.data[i] = carry;
result.size = size + 1; result.size = size + 1;
} } else {
else { result.size = size;
result.size = size; }
}
#ifdef _DEBUG_ADD #ifdef _DEBUG_ADD
std::cout << result << " capacity=" << result.capacity << ",size="<<result.size<< std::endl; std::cout << result << " capacity=" << result.
capacity << ",size=" << result.size << std::endl;
#endif #endif
return result; return result;
} }
void Number::operator+=(const Number& a) {
*this = *this + a;
}
bool Number::isEven() const { void Number::operator+=(const Number & a)
if (data[0] % 2) { {
return false; *this = *this + a;
} }
return true;
bool Number::isEven() const
{
if (data[0] % 2) {
return false;
} }
Number Number::operator*(const Number& right) const { 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; std::cout << "]" << std::endl;
#endif #endif
for (i = 0; i < size; ++i) { for (i = 0; i < size; ++i) {
for (j = 0; j < right.size; ++j) { for (j = 0; j < right.size; ++j) {
#ifdef _DEBUG_MUL #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; 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 #endif
temp = (result.data[i + j] + data[i] * right.data[j] + carry[i + j]); temp =
result.data[i + j] = temp % base; (result.data[i + j] + data[i] * right.data[j] +
carry[i + j + 1] += temp / base; carry[i + j]);
carry[i + j] = 0; result.data[i + j] = temp % base;
carry[i + j + 1] += temp / base;
carry[i + j] = 0;
} }
} }
#ifdef _DEBUG_MUL #ifdef _DEBUG_MUL
std::cout << "result before applying carry:" << result << std::endl; std::cout << "result before applying carry:" << result << std::endl;
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; std::cout << "]" << std::endl;
#endif #endif
if (carry[i + j - 1]) { if (carry[i + j - 1]) {
result.data[i + j - 1] = carry[i + j - 1]; result.data[i + j - 1] = carry[i + j - 1];
result.size = i + j; result.size = i + j;
} } else {
else { result.size = i + j - 1;
result.size = i + j - 1; }
}
#ifdef _DEBUG_MUL #ifdef _DEBUG_MUL
std::cout << "before correcting capacity, result=" << result << std::endl; std::cout << "before correcting capacity, result=" << result << std::
endl;
#endif #endif
// correcting capacity // correcting capacity
/*char* temp_data = (char *)calloc(result.size, sizeof(char)); /*char* temp_data = (char *)calloc(result.size, sizeof(char));
for (i = 0; i < result.size; ++i) { for (i = 0; i < result.size; ++i) {
temp_data[i] = result.data[i]; temp_data[i] = result.data[i];
} }
free(result.data); free(result.data);
result.capacity = result.size; result.capacity = result.size;
result.data = (char*)calloc(result.size,sizeof(char)); result.data = (char*)calloc(result.size,sizeof(char));
for (i = 0; i < result.size; ++i) { for (i = 0; i < result.size; ++i) {
result.data[i] = temp_data[i]; result.data[i] = temp_data[i];
} }
free(temp_data);*/ free(temp_data); */
free(carry); free(carry);
#ifdef _DEBUG_MUL #ifdef _DEBUG_MUL
std::cout << "return value=" << result << "(capacity=" << result.capacity << ",size=" << result.size << ")" << std::endl << "======" << std::endl; std::cout << "return value=" << result << "(capacity=" << result.
capacity << ",size=" << result.
size << ")" << std::endl << "======" << std::endl;
#endif #endif
return result; return result;
} }
void Number::operator*=(const Number& a) {
*this = *this * a;
}
bool Number::operator==(const Number& a) const { void Number::operator*=(const Number & a)
if (size != a.size) { {
return false; *this = *this * a;
} }
for (int i = 0; i < size; ++i) {
if (data[i] != a.data[i]) { bool Number::operator==(const Number & a) const
return false; {
} if (size != a.size) {
} return false;
return true;
} }
bool Number::operator!=(const Number& a) const { for (int i = 0; i < size; ++i) {
return not (*this == a); if (data[i] != a.data[i]) {
return false;
}
} }
bool Number::operator>(const Number& a) const { return true;
}
bool Number::operator!=(const Number & a) const
{
return not(*this == a);
}
bool Number::operator>(const Number & a) const
{
#ifdef _DEBUG_COMP #ifdef _DEBUG_COMP
std::cout << "comp " << *this << "(size=" << size << ") and " << a << "(size=" << a.size << ")" << std::endl; std::
cout << "comp " << *this << "(size=" << size << ") and " << a <<
"(size=" << a.size << ")" << std::endl;
#endif #endif
if (size > a.size) { if (size > a.size) {
#ifdef _DEBUG_COMP #ifdef _DEBUG_COMP
std::cout << "size > a.size => true" << std::endl; std::cout << "size > a.size => true" << std::endl;
#endif #endif
return true; return true;
} }
if (size < a.size) { if (size < a.size) {
#ifdef _DEBUG_COMP #ifdef _DEBUG_COMP
std::cout << "size < a.size => false" << std::endl; std::cout << "size < a.size => false" << std::endl;
#endif #endif
return false; return false;
} }
for (int i = size - 1; i >= 0; --i) { for (int i = size - 1; i >= 0; --i) {
if (data[i] > a.data[i]) { if (data[i] > a.data[i]) {
return true; return true;
#ifdef _DEBUG_COMP #ifdef _DEBUG_COMP
std::cout << static_cast<int>(data[i]) << ">" << static_cast<int>(a.data[i]) << std::endl; std::cout << static_cast <
int >(data[i]) << ">" << static_cast <
int >(a.data[i]) << std::endl;
#endif #endif
} }
if (data[i] < a.data[i]) { if (data[i] < a.data[i]) {
#ifdef _DEBUG_COMP #ifdef _DEBUG_COMP
std::cout << static_cast<int>(data[i]) << "<" << static_cast<int>(a.data[i]) <<std::endl; std::cout << static_cast <
int >(data[i]) << "<" << static_cast <
int >(a.data[i]) << std::endl;
#endif #endif
return false; return false;
} }
} }
#ifdef _DEBUG_COMP #ifdef _DEBUG_COMP
std::cout << "using final false" << std::endl; std::cout << "using final false" << std::endl;
#endif #endif
return false; return false;
} }
bool Number::operator<(const Number& a) const {
return not (*this > a) and (*this != a); bool Number::operator<(const Number & a) const
} {
void Number::div2() { return not(*this > a) and(*this != a);
}
void Number::div2()
{
#ifdef _DEBUG_DIV2 #ifdef _DEBUG_DIV2
std::cout << "n = " << *this << std::endl; std::cout << "n = " << *this << std::endl;
#endif #endif
int carry = 0; int carry = 0;
int temp; int temp;
for (int i = size - 1; i >= 0; --i) { for (int i = size - 1; i >= 0; --i) {
temp = data[i] + carry * base; temp = data[i] + carry * base;
data[i] = temp / 2; data[i] = temp / 2;
carry = temp % 2; carry = temp % 2;
} }
if (data[size-1] == 0) { if (data[size - 1] == 0) {
--size; --size;
} }
#ifdef _DEBUG_DIV2 #ifdef _DEBUG_DIV2
std::cout << "unstripped result "<< *this << std::endl; std::cout << "unstripped result " << *this << std::endl;
#endif #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;
} }

@ -25,39 +25,39 @@
(это упрощает многие алгоритмы с такими числами) (это упрощает многие алгоритмы с такими числами)
*/ */
class Number class Number {
{ private:
private:
static const int base = 100; static const int base = 100;
std::size_t size; std::size_t size;
std::size_t capacity; std::size_t capacity;
char* data; char *data;
public: public:
Number(int a); Number(int a);
Number(); Number();
// Конструктор копирования // Конструктор копирования
Number(const Number& n); Number(const Number & n);
Number(const char* str); Number(const char *str);
~Number(); ~Number();
Number& operator=(const Number& right); Number & operator=(const Number & right);
Number operator+(Number a); Number operator+(Number a);
void operator+=(const Number& a); void operator+=(const Number & a);
bool isEven() const; bool isEven() const;
Number operator*(const Number& right) const; Number operator*(const Number & right) const;
void operator*=(const Number& a); 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;
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(); void div2();
friend std::ostream& operator<<(std::ostream& stream, const Number& right); friend std::ostream & operator<<(std::ostream & stream,
const Number & right);
}; };
std::ostream& operator<<(std::ostream& stream, const Number& right); std::ostream & operator<<(std::ostream & stream, const Number & right);