咳咳,今天我来给大家,粗略的讲讲高精度的计算,说通俗点就是,用数组模拟精度,用字符串读入所谓的高精度数,然后把各各数位存int型数组里就ok了啦~
<1>高精度加法:
i ) 高精度大整数加法:
Description
求两个不超过200位的非负整数的和。
Input
有两行,每行是一个不超过200位的非负整数,没有多余的前导0。
Output
一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
Sample Input
22222222222222222222
33333333333333333333
Sample Output
55555555555555555555
思路:
就按照我刚才说的套路模拟一下~暴力特判一下谁的长度长,然后该进位就进位,不进位就直接加,注意数组下标的对应,显然是0难度啦~
不理解加法原理的,看一下这个链接 https://blog.csdn.net/ericgipsy/article/details/79942914
这是我不久前打的一场比赛,B题,奇怪的加法,是不进位加法,如果连不进位的你都看懂了,进位的就小case啦~
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
char s1[205], s2[205];
int a1[205], a2[205];
int ans[205];
int dis[205]; //记录当前位对下一位的进位
int main() {
scanf("%s %s", s1, s2);
int l1 = strlen(s1);
int l2 = strlen(s2);
for(int i = 0; i < l1; i++) a1[l1 - i] = s1[i] - '0';
for(int i = 0; i < l2; i++) a2[l2 - i] = s2[i] - '0';
memset(dis, 0, sizeof(dis));
memset(ans, 0, sizeof(ans));
if(l1 > l2) {
for(int i = 1; i <= l2; i++) {
ans[i] = (a1[i] + a2[i] + dis[i - 1]) % 10;
dis[i] = (a1[i] + a2[i] + dis[i - 1]) / 10;
}
for(int i = l2 + 1; i <= l1; i++) ans[i] = a1[i] + dis[i - 1];
for(int i = l1; i >= 1; i--) printf("%d", ans[i]);
printf("\n");
}
else if(l2 > l1) {
for(int i = 1; i <= l1; i++) {
ans[i] = (a1[i] + a2[i] + dis[i - 1]) % 10;
dis[i] = (a1[i] + a2[i] + dis[i - 1]) / 10;
}
for(int i = l1 + 1; i <= l2; i++) ans[i] = a2[i] + dis[i - 1];
for(int i = l2; i >= 1; i--) printf("%d", ans[i]);
printf("\n");
}
else {
for(int i = 1; i <= l1; i++) {
ans[i] = (a1[i] + a2[i] + dis[i - 1]) % 10;
dis[i] = (a1[i] + a2[i] + dis[i - 1]) / 10;
}
if(dis[l1] == 1) printf("1");
for(int i = l1; i >= 1; i--) printf("%d", ans[i]);
printf("\n");
}
}
ii ) 高精度浮点型加法:
Description
求2个浮点数相加的和。
题目中输入输出中出现浮点数都有如下的形式:
P1P2...Pi.Q1Q2...Qj
对于整数部分,P1P2...Pi是一个非负整数。
对于小数部分,Qj不等于0。
Input
第1行是测试数据的组数n,每组测试数据占2行,分别是两个加数。每组测试数据之间有一个空行,每行数据不超过100个字符。
Output
n行,每组测试数据有一行输出是相应的和。由输入保证输出一定是一个小数部分不为0的浮点数,即由输入保证输出结果至少有一位小数。
Sample Input
2
0.111111111111111111111111111111
0.111111111111111111111111111111
10000000.655555555555555555555555555555
1.444444444444444444444444444445
Sample Output
0.222222222222222222222222222222
10000002.1
思路:和上面那个区别不大,就分别对整数部分和小数部分进行两个方向的进位加法就可以啦,注意小数最高位进位要进到整数的最低位,因此,整数进位值的初始化要是小数最高位进位,详见代码注释。
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int cas;
char s1[105], s2[105];
int a1[105], a2[105]; //整数部分
int b1[105], b2[105]; //小数部分
int ans1[105], ans2[105]; //答案的整数和小数部分
int main() {
scanf("%d", &cas);
while(cas--) {
scanf("%s %s", s1, s2);
int l1 = strlen(s1), l2 = strlen(s2);
memset(ans1, 0, sizeof(ans1));
memset(ans2, 0, sizeof(ans2));
memset(a1, 0, sizeof(a1));
memset(a2, 0, sizeof(a2));
memset(b1, 0, sizeof(b1));
memset(b2, 0, sizeof(b2));
int pos1, pos2;
for(int i = 0; i < l1; i++) if(s1[i] == '.') pos1 = i;
for(int i = 0; i < l2; i++) if(s2[i] == '.') pos2 = i;
for(int i = 0; i < pos1; i++) a1[pos1 - i] = s1[i] - '0';
for(int i = 0; i < pos2; i++) a2[pos2 - i] = s2[i] - '0';
for(int i = pos1 + 1; i < l1; i++) b1[i - pos1] = s1[i] - '0';
for(int i = pos2 + 1; i < l2; i++) b2[i - pos2] = s2[i] - '0';
int ln1 = l1 - pos1, ln2 = l2 - pos2; //小数部分长度
int t = 0; //小数进位
if(ln1 > ln2) {
for(int i = ln1; i > ln2; i--) ans2[i] = b1[i];
for(int i = ln2; i >= 1; i--) {
ans2[i] = (b1[i] + b2[i] + t) % 10;
t = (b1[i] + b2[i] + t) / 10;
}
}
else if(ln1 < ln2) {
for(int i = ln2; i > ln1; i--) ans2[i] = b2[i];
for(int i = ln1; i >= 1; i--) {
ans2[i] = (b1[i] + b2[i] + t) % 10;
t = (b1[i] + b2[i] + t) / 10;
}
}
else {
for(int i = ln2; i >= 1; i--) {
ans2[i] = (b1[i] + b2[i] + t) % 10;
t = (b1[i] + b2[i] + t) / 10;
}
}
//for(int i = 1; i <= max(ln1, ln2) - 1; i++) printf("%d", ans2[i]);
int pos;
bool flg = 0;
for(int i = max(ln1, ln2) - 1; i >= 1; i--) {
if(ans2[i] != 0) {
flg = 1;
pos = i;
break;
}
}
int lnn1 = pos1, lnn2 = pos2; //整数部分长度
int p = t; //整数进位, 初始化要等与小数最高位进位
if(lnn1 > lnn2) {
for(int i = 1; i <= lnn2; i++) {
ans1[i] = (a1[i] + a2[i] + p) % 10;
p = (a1[i] + a2[i] + p) / 10;
}
for(int i = lnn2 + 1; i <= lnn1; i++) {
ans1[i] = (a1[i] + p) % 10;
p = (a1[i] + p) / 10;
}
}
else if(lnn1 < lnn2) {
for(int i = 1; i <= lnn1; i++) {
ans1[i] = (a1[i] + a2[i] + p) % 10;
p = (a1[i] + a2[i] + p) / 10;
}
for(int i = lnn1 + 1; i <= lnn2; i++) {
ans1[i] = (a2[i] + p) % 10;
p = (a2[i] + p) / 10;
}
}
else {
for(int i = 1; i <= lnn1; i++) {
ans1[i] = (a1[i] + a2[i] + p) % 10;
p = (a1[i] + a2[i] + p) / 10;
}
}
if(p == 1) printf("1");
for(int i = max(lnn1, lnn2); i>= 1; i--) printf("%d", ans1[i]);
if(flg) {
printf(".");
for(int i = 1; i <= pos; i++) printf("%d", ans2[i]);
}
printf("\n");
}
return 0;
}
<2>高精度乘法:
Description
求两个不超过200位的非负整数的积。
Input
输入有两行,每行是一个不超过200位的非负整数,没有多余的前导0。
Output
一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
Sample Input
12345678900
98765432100
Sample Output
1219326311126352690000
思路:手写一下乘法算式就能发现其中的规律了!!!一定要亲自手写一下!!!套路都是一样滴!!!
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
char s1[205], s2[205];
int a1[205], a2[205];
int ans[1005];
int main() {
char s1[1500], s2[1500];
scanf("%s %s", s1, s2);
int l1 = strlen(s1), l2 = strlen(s2);
for(int i = 0; i < l1; i++) a1[i] = s1[l1 - 1 - i] - '0';
for(int i = 0; i < l2; i++) a2[i] = s2[l2 - 1 - i] - '0';
memset(ans, 0, sizeof(ans));
for(int i = 0; i < l2; i++) {
for(int j = 0; j < l1; j++) ans[i + j] += a1[j] * a2[i];
}
for(int i = 0; i < l1 + l2; i++) {
ans[i + 1] += ans[i] / 10;
ans[i] %= 10;
}
int pos;
for(pos = 1005; pos > 0; pos--) {
if(ans[pos] != 0) break;
}
for(int i = pos; i >= 0; i--) printf("%d", ans[i]);
printf("\n");
return 0;
}
<3>高精度幂:
Description
任意给定一个正整数N(N≤100),计算2的N次方的值。
Input
输入只有一个正整数N。
Output
输出2的N次方的值。
Sample Input
5
Sample Output
32
思路:
之前ACM的一个大佬给我讲过,有个裸板子,其实最开始我也看不懂,但是你就顺着循环手推一下就明白了!举个栗子,2^n,在n == 4时,进行第一次进位变成了16, 然后再变成32,接着是64,再结合板子循环里的语句,自己认真想想,就会想通啦~
本人AC代码 -> 裸裸裸裸板子~ :
//A的n次方 高精度幂
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int A = 2;
int n;
int ans[1005];
int main() {
scanf("%d", &n);
int t = 0; //进位
ans[99] = 1;
while(n--) {
int tmp = 99;
while(tmp >= 0) {
int p = ans[tmp] * A + t;
ans[tmp] = p % 10;
t = p / 10;
tmp--;
}
}
int pos;
for(pos = 0; pos < 100; pos++) if(ans[pos] != 0) break;
while(pos < 100) {
printf("%d", ans[pos]);
pos++;
}
printf("\n");
return 0;
}