突然发现自己从来没有写过正儿八经的大数.于是在退役之前写一把.
希望能在用到大数时替代掉慢死的Python.
项目地址Github.com/Frankaiyou/LargeIntegar
话说我在Github上写了好几个东西都没怎么有人star.
看来还是太菜了.
写的很差, Bug很多.
Module
- Input
- Basically completed
- Output
- Basically completed
- Constructor
- Basically completed
- Memory management
- Incomplete
- Convert with other formats
- Basically completed
- Arithmetic operators
- Division and Multiplicaion;
- Relational operators
- Basically completed
- Logical operators
- Basically completed
- Subscript operators
- Not needed for now
ToDoList
- [ ] division;
- [ ] Multiplicaion;
- [ ] Fix the Compare;
- [ ] Possible memory leaks;
- [ ] Sub or Add is lengthy.
1.0.1
- Fixed the Output that appear Prefix zero;
Now it will remove the Prefix zero In The Substruction; - Modified the way input a LargeIntegar,
which input a string and convert it to LargeIntegar; - Calculate the memory more reasonable in substruction and addition;
- Added the new file
histort.cpp
, code that discarded place it here; - Added relational operators;
- Streamline the Add and Sub;
1.0.1.1
- Streamline the Add and Sub;
But it still very lengthy;
1.0.1.2
- Solve a Bug in
convert_string_to_largeIntegar
;
1.0.1.3
- Added relational operators: (No tested!)
'<', '>', '>=', '<=', '==', '!=' .
实现思路是用一段连续的int32
来表示整段数字, 每个int32
只用4位, 为的是方便乘法操作.
同时可以在一定程度上减少计算量(是一般方法的四分之一), 虽然编程难度变大很多.
日程
10-15
精简了部分代码
P1601 A+B Problem(高精)
OpenJudge 3736 大整数减法
#include <algorithm>
#include <iostream>
#include <string.h>
#include <sstream>
#include <istream>
#include <stdio.h>
#include <string>
using namespace std;
#define InitSize 30
#define MaxOfFBit 9999
#define CalcBit(X) (X > 999 ? 4 : (X > 99 ? 3 : (X > 9 ? 2 : (X > 0 ? 1 : 0))))
class LargeIntegar {
int *Nums, *BegPos, *EndPos, size, bit; bool Sign;
public:
LargeIntegar(int sz = InitSize) {
Sign = false, BegPos = NULL, bit = 0;
Nums = new int[sz], size = sz, EndPos = Nums + sz;
std:: fill(Nums, Nums + sz, false);
}
template <typename Int>
LargeIntegar Convert_Int_to_LargeIntegar(Int integar) {
string Str = to_string(integar);
return Convert_String_to_LargeIntegar(Str);
}
void Redistribute_Memory(int sz) {
int* NewInt = new int[sz]; EndPos = NewInt + sz;
std:: fill(NewInt, NewInt + sz, false);
memcpy(Nums, NewInt + sz - size, size * sizeof(int));
delete Nums; Nums = NewInt, size = sz;
}
static LargeIntegar Convert_String_to_LargeIntegar(string& Str) {
int sz = max(int(Str.size() + 5), InitSize);
LargeIntegar Res = LargeIntegar(sz);
int *p = Res.EndPos - 1;
while (Str[0] == '0' and Str.size() > 1) Str.erase(0, 1);
for (int i = Str.size() - 1; i >= 0; i -= 4) {
Res.BegPos = p;
if (i < 3) {
*p = Str[i] - '0', Res.bit += 1;
if (i > 0) *p += 10 * (Str[i - 1] - '0'), Res.bit += 1;
if (i > 1) *p += 100 * (Str[i - 2] - '0'), Res.bit += 1;
break;
}
*p = Str[i] - '0' + 10 * (Str[i - 1] - '0') +
(Str[i - 2] - '0') * 100 + 1000 * (Str[i - 3] - '0');
p -= 1, Res.bit += 4;
}
return Res;
}
template <typename Int>
LargeIntegar operator = (const Int& o) {
return *this = Convert_Int_to_LargeIntegar(o);
}
friend istream& operator >> (istream &in, LargeIntegar &Int) {
string str; in >> str;
Int = Convert_String_to_LargeIntegar(str);
return in;
}
friend ostream& operator << (ostream &out, LargeIntegar &lInt) {
if (not lInt.BegPos) {
out << 0; return out;
}
int* num = lInt.BegPos;
if (lInt.Sign) cout << '-';
out << *num; num += 1;
int tmp;
while (num != lInt.EndPos) {
if (*num == 0) out << "000";
else if ((tmp = CalcBit(*num)) < 4) {
tmp = 4 - tmp;
while (tmp --) putchar('0');
}
out << *num;
num += 1;
}
return out;
}
int operator ! () const {
return not(*BegPos);
}
bool operator < (const LargeIntegar& o) const {
if (not Sign and o.Sign) return false;
if (Sign and not o.Sign) return true;
if (Sign and o.Sign) return not((-(*this)) < (-o));
if (bit != o.bit) return bit < o.bit;
int *p = this->BegPos, *q = o.BegPos;
while (p != this->EndPos and q != o.EndPos) {
if (*p != *q) return *p < *q;
p = p + 1, q = q + 1;
}
return false;
}
bool operator >= (const LargeIntegar& o) const {
return not (*this < o);
}
bool operator == (const LargeIntegar& o) const {
if (not Sign and o.Sign) return false;
if (Sign and not o.Sign) return false;
if (Sign and o.Sign) return false;
if (bit != o.bit) return false;
int *p = this->BegPos, *q = o.BegPos;
while (p != this->EndPos and q != o.EndPos) {
if (*p != *q) return false;
p = p + 1, q = q + 1;
}
return true;
}
bool operator != (const LargeIntegar& o) const {
return not (*this == o);
}
bool operator > (const LargeIntegar& o) const {
return (*this >= o and not (*this == o));
}
bool operator <= (const LargeIntegar& o) const {
return not (*this > o);
}
LargeIntegar operator + (const LargeIntegar& o) const {
bool flag = false;
if (o.Sign and Sign) flag = true;
else if (o.Sign) return *this - (-o);
else if (Sign) return o - (-(*this));
if (*this < o) return o + *this;
LargeIntegar Res = LargeIntegar(max(max(bit, o.bit) + 5, InitSize));
int *p = EndPos - 1, *q = o.EndPos - 1, *r = Res.EndPos - 1;
while (p != BegPos - 1) {
*r += *p + (q == o.BegPos - 1 ? 0 : *q);
if (*r > MaxOfFBit) {
*(r - 1) += 1, *r %= MaxOfFBit + 1,
Res.BegPos = r - 1, Res.bit += 4;
}
else Res.BegPos = r, Res.bit += (p == BegPos ? CalcBit(*r) : 4);
p -= 1, q -= (q == o.BegPos - 1 ? 0 : 1), r -= 1;
}
if (flag) Res.Sign = true;
return Res;
}
LargeIntegar operator - () const {
LargeIntegar Res = *this;
Res.Sign ^= 1;
return Res;
}
LargeIntegar operator - (const LargeIntegar& o) const {
if (not Sign and o.Sign) return *this + (-o);
if (Sign and not o.Sign) return -((-(*this) + o));
if (Sign and Sign) return ((-o) - (-(*this)));
if (*this < o) return -(o - *this);
LargeIntegar Res = LargeIntegar(max(max(bit, o.bit) + 5, InitSize));
int *p = EndPos - 1, *q = o.EndPos - 1, *r = Res.EndPos - 1;
while (p != BegPos - 1) {
*r += *p - (q == o.BegPos - 1 ? 0 : *q);
if (*r < 0) *(r - 1) -= 1, *r += MaxOfFBit + 1, Res.BegPos = r - 1;
else Res.BegPos = r;
Res.bit += (p == BegPos ? CalcBit(*r) : 4);
p -= 1, q -= (q == o.BegPos - 1 ? 0 : 1), r -= 1;
}
while (*Res.BegPos == 0 and Res.BegPos < Res.EndPos - 1)
Res.BegPos += 1;
return Res;
}
};
int Test() {
LargeIntegar o, b;
cin >> o >> b;
cout << o << endl;
cout << b << endl;
printf("If A > B ? %d
", o > b);
// o = o + b;
// long long a = 123456789123456789ll;
cout << (o == b) << endl;
return 0;
}
int main () {
return Test();
}