UNPKG

oi-wiki

Version:
221 lines (212 loc) 4.94 kB
什么时候需要高精度呢?就比如数据规模很大,unsigned long long 都存不下,就需要开一个字符数组来准确地表示一个数。 高精度问题包含很多小的细节,实现上也有很多讲究,暂时先不展开。 - 四则运算 - 快速幂 - 分数 - 对数(?) - 开根 - 压位高精度 放一个之前的高精度板子吧。 还有一个很好用的[高精度封装类](https://paste.ubuntu.com/p/7VKYzpC7dn/) 10kb 想用可以自行下载。 ```c++ #define MAXN 9999 //MAXN 是一位中最大的数字 #define MAXSIZE 10024 //MAXSIZE 是位数 #define DLEN 4 //DLEN 记录压几位 struct Big{ int a[MAXSIZE],len; bool flag;//标记符号'-' Big(){len = 1;memset(a,0,sizeof a);flag = 0;} Big(const int); Big(const char*); Big(const Big&); Big &operator = (const Big &);//注意这里operator有&,因为赋值有修改…… //由于OI中要求效率 //此处不使用泛型函数 //故不重载 //istream& operator>>(istream&, BigNum&); //重载输入运算符 //ostream& operator<<(ostream&, BigNum&); //重载输出运算符 Big operator + (const Big &)const; Big operator - (const Big &)const; Big operator * (const Big &)const; Big operator / (const int &)const; //TODO: Big / Big; Big operator ^ (const int &)const; //TODO: Big ^ Big; //TODO: Big 位运算; int operator % (const int &)const; //TODO: Big ^ Big; bool operator < (const Big &)const; bool operator < (const int &t)const; inline void print(); }; //README::不要随随便便把参数都变成引用,那样没办法传值 Big::Big(const int b){ int c,d = b; len = 0; // memset(a,0,sizeof a); CLR(a); while (d > MAXN){ c = d - (d / (MAXN + 1) * (MAXN + 1)); d = d / (MAXN + 1); a[len++] = c; } a[len++] = d; } Big::Big(const char* s){ int t,k,index,l; CLR(a); l = strlen(s); len = l / DLEN; if (l % DLEN)++len; index = 0; for(int i = l - 1;i >= 0;i -= DLEN){ t = 0; k = i - DLEN + 1; if (k < 0)k = 0; g(j,k,i)t = t * 10 + s[j] - '0'; a[index++] = t; } } Big::Big(const Big& T):len(T.len){ CLR(a); f(i,0,len)a[i] = T.a[i]; // TODO:重载此处? } Big& Big::operator = (const Big& T){ CLR(a); len = T.len; f(i,0,len)a[i] = T.a[i]; return *this; } Big Big::operator + (const Big& T)const{ Big t(*this); int big = len; if (T.len > len)big = T.len; f(i,0,big){ t.a[i] += T.a[i]; if (t.a[i] > MAXN){ ++t.a[i + 1]; t.a[i] -= MAXN + 1; } } if (t.a[big])t.len = big + 1; else t.len = big; return t; } Big Big::operator - (const Big& T)const{ int big; bool ctf; Big t1,t2; if (*this < T){ t1 = T; t2 = *this; ctf = 1; }else { t1 =*this; t2 = T; ctf = 0; } big = t1.len; int j = 0; f(i,0,big){ if (t1.a[i] < t2.a[i]){ j = i + 1; while (t1.a[j] == 0)++j; --t1.a[j--]; //WTF? while (j > i)t1.a[j--] += MAXN; t1.a[i] += MAXN + 1 - t2.a[i]; }else t1.a[i] -= t2.a[i]; } t1.len = big; while (t1.len > 1 && t1.a[t1.len - 1] == 0){ --t1.len; --big; } if (ctf)t1.a[big - 1] = -t1.a[big - 1]; return t1; } Big Big::operator * (const Big& T)const{ Big res; int up; int te,tee; f(i,0,len){ up = 0; f(j,0,T.len){ te = a[i] * T.a[j] + res.a[i + j] + up; if (te > MAXN){ tee = te - te / (MAXN + 1) * (MAXN + 1); up = te / (MAXN + 1); res.a[i + j] = tee; }else { up = 0; res.a[i + j] = te; } } if (up)res.a[i + T.len] = up; } res.len = len + T.len; while (res.len > 1 && res.a[res.len - 1] == 0)--res.len; return res; } Big Big::operator / (const int& b)const{ Big res; int down = 0; gd(i,len - 1,0){ res.a[i] = (a[i] + down * (MAXN + 1) / b); down = a[i] + down * (MAXN + 1) - res.a[i] * b; } res.len = len; while (res.len > 1 && res.a[res.len - 1] == 0)--res.len; return res; } int Big::operator % (const int& b)const { int d = 0; gd(i,len - 1,0)d = (d * (MAXN + 1) % b + a[i]) % b; return d; } Big Big::operator ^ (const int& n)const{ Big t(n),res(1); //TODO::快速幂这样写好丑= =//DONE:) int y = n; while (y){ if (y & 1)res = res * t; t = t * t; y >>= 1; } return res; } bool Big::operator < (const Big& T)const { int ln; if (len < T.len)return 233; if (len == T.len){ ln = len - 1; while (ln >= 0 && a[ln] == T.a[ln])--ln; if (ln >= 0 && a[ln] < T.a[ln])return 233; return 0; } return 0; } inline bool Big::operator < (const int &t)const{ Big tee(t); return *this < tee; } inline void Big::print(){ printf("%d",a[len - 1]); gd(i,len - 2,0){ printf("%04d",a[i]); } } inline void print(Big s){ //s不要是引用,要不然你怎么print(a * b); int len = s.len; printf("%d",s.a[len - 1]); gd(i,len - 2,0){ printf("%04d",s.a[i]); } } char s[100024]; ```