From d3606e22d132f36ef7b0c08f5f1d22d0bddc4d0f Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Sat, 28 Oct 2023 15:38:49 +0800 Subject: [PATCH] upd: begin writing add --- data/CMakeLists.txt | 2 +- include/int2048.h | 12 +++ src/CMakeLists.txt | 2 +- src/int2048.cpp | 196 +++++++++++++++++++++++++++++++++++++++----- tester/config.json | 2 +- 5 files changed, 192 insertions(+), 22 deletions(-) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index a75a0dc..78cb5b2 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,6 +1,6 @@ set(PROJECT_NAME ${CMAKE_PROJECT_NAME}) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "-g -O2") +set(CMAKE_CXX_FLAGS "-g") set(ENV{MAKEFLAGS} "-j16") include_directories(${PROJECT_SOURCE_DIR}/include) link_directories(${PROJECT_SOURCE_DIR}/src) diff --git a/include/int2048.h b/include/int2048.h index c0f4fda..82e24e4 100644 --- a/include/int2048.h +++ b/include/int2048.h @@ -10,6 +10,11 @@ namespace sjtu { 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; const static int kMod = 100000000, kNum = 8, kDefaultLength = 10; const static int kMemAdditionScalar = 2, kMemDeleteScalar = 4; @@ -22,10 +27,16 @@ class int2048 { int2048(long long); int2048(const std::string &); int2048(const int2048 &); + int2048 (int2048 &&) noexcept; void read(const std::string &); 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 &); friend int2048 add(int2048, const int2048 &); @@ -36,6 +47,7 @@ class int2048 { int2048 operator-() const; int2048 &operator=(const int2048 &); + int2048 &operator=(int2048 &&) noexcept; int2048 &operator+=(const int2048 &); friend int2048 operator+(int2048, const int2048 &); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 22fa710..ef0718e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ set(PROJECT_NAME ${CMAKE_PROJECT_NAME}) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "-g -O2") +set(CMAKE_CXX_FLAGS "-g") include_directories(${PROJECT_SOURCE_DIR}/include) add_library(int2048 STATIC int2048.cpp) \ No newline at end of file diff --git a/src/int2048.cpp b/src/int2048.cpp index f4f3b91..04a1ea5 100644 --- a/src/int2048.cpp +++ b/src/int2048.cpp @@ -25,6 +25,7 @@ #include #include +#include namespace sjtu { // 构造函数 int2048::int2048() { @@ -60,7 +61,7 @@ int2048::int2048(long long 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](); flag = 1; num_length = 0; @@ -89,10 +90,18 @@ int2048::int2048(const int2048 &input_value) { 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) { delete[] val; - buf_length = input_value.length() / kNum * kMemAdditionScalar; + buf_length = (input_value.length() + kNum - 1) / kNum * kMemAdditionScalar; val = new int[buf_length](); flag = 1; num_length = 0; @@ -123,54 +132,167 @@ void int2048::print() { 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 { // 实现一元加法逻辑 + return int2048(*this); } 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 &) { @@ -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 diff --git a/tester/config.json b/tester/config.json index 95f0271..d085bfb 100644 --- a/tester/config.json +++ b/tester/config.json @@ -1,5 +1,5 @@ { - "StatusInterpreter":{"0":"OK","1":"Error","139":"Segmentation fault"}, + "StatusInterpreter":{"0":"OK","1":"Wrong Answer","139":"Segmentation fault"}, "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"},