upd: begin writing add

This commit is contained in:
2023-10-28 15:38:49 +08:00
parent f23620a931
commit d3606e22d1
5 changed files with 192 additions and 22 deletions

View File

@ -1,6 +1,6 @@
set(PROJECT_NAME ${CMAKE_PROJECT_NAME}) set(PROJECT_NAME ${CMAKE_PROJECT_NAME})
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-g -O2") set(CMAKE_CXX_FLAGS "-g")
set(ENV{MAKEFLAGS} "-j16") set(ENV{MAKEFLAGS} "-j16")
include_directories(${PROJECT_SOURCE_DIR}/include) include_directories(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/src) link_directories(${PROJECT_SOURCE_DIR}/src)

View File

@ -10,6 +10,11 @@
namespace sjtu { namespace sjtu {
class int2048 { class int2048 {
/**
* If the interger is negative, flag = -1, otherwise flag = 1.
* num_length is the length of the integer, (num_length+kNum-1)/kNum is the
* length of val with data. Note that position in val without data is 0.
*/
size_t buf_length = 0; size_t buf_length = 0;
const static int kMod = 100000000, kNum = 8, kDefaultLength = 10; const static int kMod = 100000000, kNum = 8, kDefaultLength = 10;
const static int kMemAdditionScalar = 2, kMemDeleteScalar = 4; const static int kMemAdditionScalar = 2, kMemDeleteScalar = 4;
@ -22,10 +27,16 @@ class int2048 {
int2048(long long); int2048(long long);
int2048(const std::string &); int2048(const std::string &);
int2048(const int2048 &); int2048(const int2048 &);
int2048 (int2048 &&) noexcept;
void read(const std::string &); void read(const std::string &);
void print(); void print();
void ClaimMem(size_t);
inline friend int UnsignedCmp(const int2048 &A,const int2048 &B);
inline friend void UnsignedAdd(int2048 &,const int2048 *pB);
inline friend void UnsignedMinus(int2048 &,const int2048 *pB);
int2048 &add(const int2048 &); int2048 &add(const int2048 &);
friend int2048 add(int2048, const int2048 &); friend int2048 add(int2048, const int2048 &);
@ -36,6 +47,7 @@ class int2048 {
int2048 operator-() const; int2048 operator-() const;
int2048 &operator=(const int2048 &); int2048 &operator=(const int2048 &);
int2048 &operator=(int2048 &&) noexcept;
int2048 &operator+=(const int2048 &); int2048 &operator+=(const int2048 &);
friend int2048 operator+(int2048, const int2048 &); friend int2048 operator+(int2048, const int2048 &);

View File

@ -1,5 +1,5 @@
set(PROJECT_NAME ${CMAKE_PROJECT_NAME}) set(PROJECT_NAME ${CMAKE_PROJECT_NAME})
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-g -O2") set(CMAKE_CXX_FLAGS "-g")
include_directories(${PROJECT_SOURCE_DIR}/include) include_directories(${PROJECT_SOURCE_DIR}/include)
add_library(int2048 STATIC int2048.cpp) add_library(int2048 STATIC int2048.cpp)

View File

@ -25,6 +25,7 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <utility>
namespace sjtu { namespace sjtu {
// 构造函数 // 构造函数
int2048::int2048() { int2048::int2048() {
@ -60,7 +61,7 @@ int2048::int2048(long long input_value) {
int2048::int2048(const std::string &input_value) { int2048::int2048(const std::string &input_value) {
// 实现构造函数逻辑 // 实现构造函数逻辑
buf_length = input_value.length() / kNum * kMemAdditionScalar; buf_length = (input_value.length() + kNum - 1) / kNum * kMemAdditionScalar;
val = new int[buf_length](); val = new int[buf_length]();
flag = 1; flag = 1;
num_length = 0; num_length = 0;
@ -89,10 +90,18 @@ int2048::int2048(const int2048 &input_value) {
num_length = input_value.num_length; num_length = input_value.num_length;
} }
int2048::int2048(int2048 &&input_value) noexcept {
buf_length = input_value.buf_length;
val = input_value.val;
flag = input_value.flag;
num_length = input_value.num_length;
input_value.val = nullptr;
}
// 读入一个大整数 // 读入一个大整数
void int2048::read(const std::string &input_value) { void int2048::read(const std::string &input_value) {
delete[] val; delete[] val;
buf_length = input_value.length() / kNum * kMemAdditionScalar; buf_length = (input_value.length() + kNum - 1) / kNum * kMemAdditionScalar;
val = new int[buf_length](); val = new int[buf_length]();
flag = 1; flag = 1;
num_length = 0; num_length = 0;
@ -123,54 +132,167 @@ void int2048::print() {
putchar('0' + val[i / kNum] / kPow10[i % kNum] % 10); putchar('0' + val[i / kNum] / kPow10[i % kNum] % 10);
} }
void int2048::ClaimMem(size_t number_length) {
size_t new_number_blocks = (number_length + kNum - 1) / kNum;
if (new_number_blocks > buf_length) {
int *new_val = new int[new_number_blocks * kMemAdditionScalar]();
memcpy(new_val, val, buf_length * sizeof(int));
delete[] val;
val = new_val;
buf_length = new_number_blocks * kMemAdditionScalar;
} else if (new_number_blocks * kMemDeleteScalar < buf_length) {
int *new_val = new int[new_number_blocks * kMemAdditionScalar]();
memcpy(new_val, val, new_number_blocks * sizeof(int));
delete[] val;
val = new_val;
buf_length = new_number_blocks * kMemAdditionScalar;
}
}
inline int UnsignedCmp(const int2048 &A, const int2048 &B) {
if (A.num_length != B.num_length) return A.num_length < B.num_length ? -1 : 1;
int number_of_blocks = (A.num_length + A.kNum - 1) / A.kNum;
for (int i = number_of_blocks - 1; i >= 0; i--)
if (A.val[i] != B.val[i]) return A.val[i] < B.val[i] ? -1 : 1;
return 0;
}
inline void UnsignedAdd(int2048 &A, const int2048 *const pB) {
if (&A == pB) throw "UnsignedAdd: A and B are the same object";
A.ClaimMem(std::max(A.num_length, pB->num_length) + 2);
for (int i = 0;
i < (std::max(A.num_length, pB->num_length) + A.kNum - 1) / A.kNum;
i++) {
if (i < (pB->num_length + pB->kNum - 1) / pB->kNum) A.val[i] += pB->val[i];
A.val[i + 1] += A.val[i] / A.kMod;
A.val[i] %= A.kMod;
}
A.num_length = std::max(A.num_length, pB->num_length);
const static int kPow10[9] = {1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000};
if (A.val[A.num_length / A.kNum] / kPow10[A.num_length % A.kNum] > 0)
A.num_length++;
}
inline void UnsignedMinus(int2048 &A, const int2048 *const pB) {
if (&A == pB) throw "UnsignedMinus: A and B are the same object";
;
}
// 加上一个大整数 // 加上一个大整数
int2048 &int2048::add(const int2048 &) { int2048 &int2048::add(const int2048 &B) {
// 实现加法逻辑 // 实现加法逻辑
const int2048 *pB = &B;
if (this->flag == pB->flag) {
if (this == &B) pB = new int2048(B);
UnsignedAdd(*this, pB);
} else if (this->flag == 1 && pB->flag == -1) {
int cmp = UnsignedCmp(*this, *pB);
if (cmp >= 0) {
if (this == &B) pB = new int2048(B);
UnsignedMinus(*this, pB);
this->flag = 1;
} else {
int2048 new_B = std::move(*this);
*this = B;
UnsignedMinus(*this, &new_B);
this->flag = -1;
}
} else if (this->flag == -1 && pB->flag == 1) {
int cmp = UnsignedCmp(*this, *pB);
if (cmp >= 0) {
if (this == &B) pB = new int2048(B);
UnsignedMinus(*this, pB);
this->flag = -1;
} else {
int2048 new_B = std::move(*this);
*this = B;
UnsignedMinus(*this, &new_B);
this->flag = 1;
}
}
return *this;
} }
// 返回两个大整数之和 // 返回两个大整数之和
int2048 add(int2048, const int2048 &) { int2048 add(int2048 A, const int2048 &B) {
// 实现加法逻辑 // 实现加法逻辑
return A.add(B);
} }
// 减去一个大整数 // 减去一个大整数
int2048 &int2048::minus(const int2048 &) { int2048 &int2048::minus(const int2048 &B) {
// 实现减法逻辑 // 实现减法逻辑
const int2048 *pB = &B;
if (this == &B) pB = new int2048(B);
UnsignedMinus(*this, pB);
return *this;
} }
// 返回两个大整数之差 // 返回两个大整数之差
int2048 minus(int2048, const int2048 &) { int2048 minus(int2048 A, const int2048 &B) {
// 实现减法逻辑 // 实现减法逻辑
return A.minus(B);
} }
// 运算符重载 // 运算符重载
int2048 int2048::operator+() const { int2048 int2048::operator+() const {
// 实现一元加法逻辑 // 实现一元加法逻辑
return int2048(*this);
} }
int2048 int2048::operator-() const { int2048 int2048::operator-() const {
// 实现一元减法逻辑 // 实现一元减法逻辑
int2048 ret(*this);
if (!(ret.num_length == 1 && ret.val[0] == 0)) ret.flag = -ret.flag;
return ret;
} }
int2048 &int2048::operator=(const int2048 &) { int2048 &int2048::operator=(const int2048 &B) {
// 实现赋值运算符逻辑 // 实现赋值运算符逻辑
// similar to int2048::int2048(const int2048 &input_value)
if (this == &B) return *this;
delete[] val;
buf_length = B.buf_length;
val = new int[buf_length]();
memcpy(val, B.val, buf_length * sizeof(int));
flag = B.flag;
num_length = B.num_length;
return *this;
} }
int2048 &int2048::operator+=(const int2048 &) { int2048 &int2048::operator=(int2048 &&B) noexcept {
// 实现移动赋值运算符逻辑
if (this == &B) return *this;
delete[] val;
buf_length = B.buf_length;
val = B.val;
flag = B.flag;
num_length = B.num_length;
B.val = nullptr;
return *this;
}
int2048 &int2048::operator+=(const int2048 &B) {
// 实现复合加法逻辑 // 实现复合加法逻辑
return this->add(B);
} }
int2048 operator+(int2048, const int2048 &) { int2048 operator+(int2048 A, const int2048 &B) {
// 实现加法逻辑 // 实现加法逻辑
A.add(B);
return A;
} }
int2048 &int2048::operator-=(const int2048 &) { int2048 &int2048::operator-=(const int2048 &B) {
// 实现复合减法逻辑 // 实现复合减法逻辑
return this->minus(B);
} }
int2048 operator-(int2048, const int2048 &) { int2048 operator-(int2048 A, const int2048 &B) {
// 实现减法逻辑 // 实现减法逻辑
A.minus(B);
return A;
} }
int2048 &int2048::operator*=(const int2048 &) { int2048 &int2048::operator*=(const int2048 &) {
@ -197,35 +319,71 @@ int2048 operator%(int2048, const int2048 &) {
// 实现取模逻辑 // 实现取模逻辑
} }
std::istream &operator>>(std::istream &, int2048 &) { std::istream &operator>>(std::istream &stream, int2048 &V) {
// 实现输入运算符逻辑 // 实现输入运算符逻辑
std::string v_str;
stream >> v_str;
V.read(v_str);
} }
std::ostream &operator<<(std::ostream &, const int2048 &) { std::ostream &operator<<(std::ostream &stream, const int2048 &v) {
// 实现输出运算符逻辑 // 实现输出运算符逻辑
if (v.flag == -1) stream << '-';
const static int kPow10[9] = {1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000};
for (int i = v.num_length - 1; i >= 0; i--)
stream << char('0' + v.val[i / v.kNum] / kPow10[i % v.kNum] % 10);
} }
bool operator==(const int2048 &, const int2048 &) { bool operator==(const int2048 &A, const int2048 &B) {
// 实现等于运算符逻辑 // 实现等于运算符逻辑
if (A.flag != B.flag) return false;
return UnsignedCmp(A, B) == 0;
} }
bool operator!=(const int2048 &, const int2048 &) { bool operator!=(const int2048 &A, const int2048 &B) {
// 实现不等于运算符逻辑 // 实现不等于运算符逻辑
if (A.flag != B.flag) return true;
return UnsignedCmp(A, B) != 0;
} }
bool operator<(const int2048 &, const int2048 &) { bool operator<(const int2048 &A, const int2048 &B) {
// 实现小于运算符逻辑 // 实现小于运算符逻辑
if (A.flag != B.flag) return A.flag < B.flag;
int cmp = UnsignedCmp(A, B);
if (A.flag == 1)
return cmp < 0;
else
return cmp > 0;
} }
bool operator>(const int2048 &, const int2048 &) { bool operator>(const int2048 &A, const int2048 &B) {
// 实现大于运算符逻辑 // 实现大于运算符逻辑
if (A.flag != B.flag) return A.flag > B.flag;
int cmp = UnsignedCmp(A, B);
if (A.flag == 1)
return cmp > 0;
else
return cmp < 0;
} }
bool operator<=(const int2048 &, const int2048 &) { bool operator<=(const int2048 &A, const int2048 &B) {
// 实现小于等于运算符逻辑 // 实现小于等于运算符逻辑
if (A.flag != B.flag) return A.flag < B.flag;
int cmp = UnsignedCmp(A, B);
if (A.flag == 1)
return cmp <= 0;
else
return cmp >= 0;
} }
bool operator>=(const int2048 &, const int2048 &) { bool operator>=(const int2048 &A, const int2048 &B) {
// 实现大于等于运算符逻辑 // 实现大于等于运算符逻辑
if (A.flag != B.flag) return A.flag > B.flag;
int cmp = UnsignedCmp(A, B);
if (A.flag == 1)
return cmp >= 0;
else
return cmp <= 0;
} }
} // namespace sjtu } // namespace sjtu

View File

@ -1,5 +1,5 @@
{ {
"StatusInterpreter":{"0":"OK","1":"Error","139":"Segmentation fault"}, "StatusInterpreter":{"0":"OK","1":"Wrong Answer","139":"Segmentation fault"},
"Cases": "Cases":
[ [
{"command":"timeout -s 9 10s /home/happyzym/CSWorkSpace/Proc/BigHomework/BH-int2048-2023/build/data/C1T1 >/tmp/C1T1.out && diff -b -B -u /tmp/C1T1.out /home/happyzym/CSWorkSpace/Proc/BigHomework/BH-int2048-2023/data/Integer1/1.out","uid":"#1","tid":"/1/1"}, {"command":"timeout -s 9 10s /home/happyzym/CSWorkSpace/Proc/BigHomework/BH-int2048-2023/build/data/C1T1 >/tmp/C1T1.out && diff -b -B -u /tmp/C1T1.out /home/happyzym/CSWorkSpace/Proc/BigHomework/BH-int2048-2023/data/Integer1/1.out","uid":"#1","tid":"/1/1"},