加法进位: 下标地位是个位,高位是十位、百位。输出的时候倒着输出。计算着时候必须先存储个位
c[i] = a[i] + b[i];
if(c[i] >= 10){ //高位进位
c[i] %= 10;
c[i+1]++;
}
减法进位: a[i]-b[i]
if(a[i] < b[i]){
a[i+1]--; //高位借位
a[i] += 10;
}
c[i] = a[i] - b[i];
乘法进位 : 看不懂,下面会解释
e[i+j-1] = c[i] * d[j] + e[i+j-1]; //新计算的值+累计原位置的值
if(e[i+j-1] >= 10){
e[i+j] += e[i+j-1] / 10; // 进位
e[i+j-1] = e[i+j-1] % 10;
}
http://ybt.ssoier.cn:8088/problem_show.php?pid=1168
求两个不超过200位的非负整数的和。
有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。
一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
22222222222222222222
33333333333333333333
55555555555555555555
#include
using namespace std;
const int maxn = 205;
char m[maxn],n[maxn];
int a[maxn],b[maxn],c[maxn];
int main(int argc, char const *argv[]){
cin >> m >> n;
int lenA = strlen(m),lenB = strlen(n);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
//char数组转为int数组,同时倒置,个位存储下标低的, 为了计算方便
for(int i = 0; i < lenA; i++) a[lenA-i-1] = m[i] - '0';
for(int i = 0; i < lenB; i++) b[lenB-i-1] = n[i] - '0';
int maxLen = max(lenA,lenB);
for(int i = 0; i < maxLen; i++){
c[i] += a[i] + b[i];
if(c[i] >= 10){
c[i] %= 10;
c[i+1]++;
}
}
//去除c的后置0
int p = maxn-1;
while(c[p] == 0){
p--;
}
for(int i = p; i >= 0; i--) cout << c[i];
return 0;
}
http://ybt.ssoier.cn:8088/problem_show.php?pid=1169
求两个大的正整数相减的差。
共2行,第1行是被减数a,第2行是减数b(a > b)。每个大整数不超过200位,不会有多余的前导零。
一行,即所求的差。
9999999999999999999999999999999999999
9999999999999
9999999999999999999999990000000000000
#include
using namespace std;
const int maxn = 205;
char a[maxn],b[maxn];
int c[maxn],d[maxn],e[maxn];
int main(int argc, char const *argv[]){
cin >> a >> b;
int lenA = strlen(a),lenB = strlen(b);
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
for(int i = 0; i < lenA; i++) c[i] = a[lenA-i-1] - '0';
for(int i = 0; i < lenB; i++) d[i] = b[lenB-i-1] - '0';
for(int i = 0; i < lenA; i++){
e[i] += c[i] - d[i];
if(e[i] < 0){
e[i+1]--;
e[i]+= 10;
}
}
int p = maxn;
while(e[p] == 0) p--;
for(int i = p; i >= 0; i--){
cout << e[i];
}
return 0;
}
c[i] 与 a[i]*b[j]的乘积、进位、原来的c[i]有关
#include
using namespace std;
const int maxn = 105;
char a[maxn],b[maxn];
int c[maxn],d[maxn],e[maxn*2];
int main(int argc, char const *argv[]){
cin >> a >> b;
int lenA = strlen(a),lenB = strlen(b);
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(e,0,sizeof(e));
for(int i = 0; i < lenA; i++) c[lenA-i] = a[i] - '0';
for(int i = 0; i < lenB; i++) d[lenB-i] = b[i] - '0';
// c[1]至c[lenA] d[1]至d[lenB] ,从低位至高位
for(int i = 1; i <= lenA; i++){
for(int j = 1; j <= lenB; j++){
e[i+j-1] = c[i] * d[j] + e[i+j-1]; //新计算的值+累计原位置的值
if(e[i+j-1] >= 10){
e[i+j] += e[i+j-1] / 10; // 进位
e[i+j-1] = e[i+j-1] % 10;
}
}
}
int p = maxn*2-1;
while(e[p] == 0) p--;
for(int i = p; i >= 1; i--) cout << e[i];
return 0;
}
做除法时,每一次的商的值都在0~9,每次求得的余数连接以后的若干位得到的新的被除数,继续做除法。因此,在做高精度除法时,要涉及到乘法运算和减法运算,还有移位处理。
当然为了程序简洁,可以避免高精度乘法,用0~9次循环减法取代商的值。
这里,我们讨论一下高精度数除以当精度数的结果,采取的方法是按位相除法。
#include
using namespace std;
int main(int argc, char const *argv[]) {
char a1[100];
int a[100],c[100];
int lenA,lenC,i,x = 0,b;
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
cin >> a1 >> b;
lenA = strlen(a1);
for(int i = 0; i < lenA; i++) a[i+1] = a1[i] - '0';
// a[1]至a[lenA]
for(int i = 1; i <= lenA; i++){
c[i] = (x*10+a[i]) / b;
x = (x*10+a[i]) % b; //表示余数
}
lenC = 1;
while(c[lenC] == 0 && lenC < lenA) lenC++;
for(int i = lenC; i <= lenA; i++) cout << c[i];
cout << endl;
return 0;
}
实质上,在做高精度数运算的时候,存储高精度数的数组元素可以不仅仅只保留一位数字,而可以采取保留多位数,这样,在做运算,特别是乘法运算时,可以减少很多操作。
用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数。
有点难。暂且放下