upd: begin writing add
This commit is contained in:
@ -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)
|
||||||
|
@ -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 &);
|
||||||
|
@ -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)
|
196
src/int2048.cpp
196
src/int2048.cpp
@ -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
|
||||||
|
@ -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"},
|
||||||
|
Reference in New Issue
Block a user