高精度整数运算的模板。
为了节省空间,此处不将运算封装成为一个类。
字符串变为高精度数
高精度整数用的比较多的是将大数变成一个万进制数,用一个数组储存。数组的第一位为万进制数的长度。1
2
3
4
5
6
7
8
9
10
11int ten[] = {1, 10, 100, 1000};
inline void clearZero(int *bi){
while(bi[0] && !bi[bi[0]]) --bi[0];
}
void build(char *src, int *dst){
int len = strlen(src);
dst[0] = (len - 1) / 4 + 1;
for(int i = len - 1, j = 0; i >= 0; --i, ++j)
dst[(j >> 2) + 1] = (src[i] - '0') * ten[j & 3];
clearZero(dst);
}
高精度比较
和字符串比大小差不多。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//前者小于后者?
bool cmp1(int *s1, int *s2){
if(s1[0] != s2[0]) return s1[0] < s2[0];
for(int i = s1[0]; i >= 1; --i)
if(s1[i] != s2[i]) return s1[i] < s2[i];
return false;
}
//小于等于
bool cmp2(int *s1, int *s2){
if(s1[0] != s2[0]) return s1[0] < s2[0];
for(int i = s1[0]; i >= 1; --i)
if(s1[i] != s2[i]) return s1[i] < s2[i];
return true;
}
//等于
bool cmp3(int *s1, int *s2){
for(int i = 0; i <= s1[0]; ++i)
if(s1[i] != s2[i]) return false;
return true;
}
高精度加法
从最低位开始加,一直加到更大数的最高位。1
2
3
4
5
6
7void add(int *s1, int *s2, int *dst){
int len = max(s1[0], s2[0]), x = 0;
dst[0] = len;
for(int i = 1; i <= len; ++i)
x += s1[i] + s2[i], dst[i] = x % 10000, x /= 10000;
if(x > 0) dst[++dst[0]] = x;
}
如果不支持不停的memset
那就改写成这样:1
2
3
4
5
6
7
8
9
10
11
12void add(int *s1, int *s2, int *dst){
int len1 = max(s1[0], s2[0]), len2 = s1[0] + s2[0] - len1, x = 0;
dst[0] = len1;
int *smax;
if(s1[0] == len1) smax = s1;
else smax = s2;
for(int i = 1; i <= len2; ++i)
x += s1[i] + s2[i], dst[i] = x % 10000, x /= 10000;
for(int i = len2 + 1; i <= len1; ++i)
x += smax[i], dst[i] = x % 10000, x /= 10000;
if(x > 0) dst[++dst[0]] = x;
}
高精度减法
默认为$a-b$,因为负数不太好实现。
高精度乘法
乘一个小于10000的数
乘一个大数
高精度左移
直接执行对该数乘上2。
高精度幂
高精度除法
高精度开方
高精度GCD
直接使用Stein算法。
void gcd(int s1, int s2, int *dst){
dst[0] = dst[1] = 1;
}