整理一下高精度的代码和题目(不处理负数)
加法:Tzoj 1192
减法:Tzoj 1250
除法:Tzoj 5710
乘法:Tzoj 5709
首先是两个转换函数:
void tolnt(int arr[], string s) {
int len = s.length(), m = 0;
for (int i = len - 1; i >= 0; i--) {
arr[m++] = s[i] - '0';
}
}
string toString(int arr[], int n) {
string res;
for (int i = n - 1; i >= 0; i--) {
res += (char)(arr[i] + '0');
}
return res;
}
A + B Problem (加):
1. 注意加法中进位最多为一, 可任选一个数组保存进位;
2. len 选择最大的字符串长度, 保证运算完整;
3. 完成运算后关注a[len] 是否有进位, 因为for循环只计算到 len - 1;
string Add(string s1, string s2) {
int a[N], b[N], c[N];
tolnt(a, s1); tolnt(b, s2);
int m = 0, len = max(s1.length(), s2.length());
for (int i = 0; i < len; i++) {
int t = a[i] + b[i];
if (t >= 10) {
c[m++] = t % 10;
a[i + 1] += 1;
}
else {
c[m++] = t;
}
}
if (a[len]) c[m++] = 1;
while (m > 0 && c[m - 1] == 0) m--;
if (m == 0) return "0";
return toString(c, m);
}
两数相减:
减法中需判断两数的大小:
字符串的比较从0 - s.size() - 1, 遵循字典序的同时由单次比较决定(相同则继续,不同则得出结论, 不再比较接下来的字符);
bool cmp(string s1, string s2) {
if (s1.length() != s2.length()) return s1.length() > s2.length();
return s1 >= s2;
}
1. swap 保证s1 >= s2;
2. 进位处理与加法相同;
string Minus(string s1, string s2) {
bool f = false;
if (!cmp(s1, s2)) {
f = true;
swap(s1, s2);
}
int a[N], b[N], c[N];
tolnt(a, s1); tolnt(b, s2);
int len = s1.length(), m = 0;
for (int i = 0; i < len; i++) {
int t = a[i] - b[i];
if (t < 0) {
c[m++] = t + 10;
a[i + 1]--;
}
else {
c[m++] = t;
}
}
while (m > 0 && c[m - 1] == 0) m--;
if (m == 0) return "0";
string res = toString(c, m);
if (f) res = "-" + res;
return res;
}
高精除:
1. 数学运算中我们的除法由乘法和件法共同完成, 本文采用减法模拟;
2. string t 为被除数的切片, 首先取除数长度的t, 之后每次取一位;
3. cmp函数保证t 大于s2, 以便每次减去s2;
4. x++ 最终的结果等同于(8 / 2) 后的 4, 当然也可以是(86 / 2)中的 十位数 4 和个位数3;
5. s3 != "" || x != 0 保证第一位不为0, 同时其他位的0可被纳入结果;
6. while (k < len - 1 && t[k] == '0') t.erase(t.begin()),每次运算后可能有前导0;
string Divide(string s1, string s2, string &s3) {
int i = s2.length();
string t = s1.substr(0, i);
while (true) {
int k = 0, len = t.length();
int x = 0;
while (k < len - 1 && t[k] == '0') t.erase(t.begin());
while (cmp(t, s2)) {
t = Minus(t, s2);
x++;
}
if (s3 != "" || x != 0) s3 += (x + '0');
if (i >= s1.length()) break;
t += s1[i++];
}
int len = t.size();
while (len > 1 && t[len - 1] == '0') t.erase(t.end() - 1);
return t;
}
7. 别忘了除数大于被除数的特判;
高精乘:
1. c数组需要清空;
2.len 乘法最大位;
string Multi(string s1, string s2) {
int a[N], b[N], c[N << 1] = {0};
tolnt(a, s1); tolnt(b, s2);
int len_a = s1.length(), len_b = s2.length();
int j;
for (int i = 0; i < len_a; i++) {
int step = 0;
for (j = 0; j < len_b; j++) {
c[i + j] += a[i] * b[j] + step;
step = c[i + j] / 10;
c[i + j] %= 10;
}
c[i + j] = step;
}
int m = len_a + len_b;
while (m > 0 && c[m - 1] == 0) m--;
if (m == 0) return "0";
return toString(c, m);
}