一本通-高精度计算

1. 进位、借位处理

加法进位: 下标低位是个位,高位是十位、百位。输出的时候倒着输出。计算着时候必须先存储个位

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;	
}

2. 高精度加法

个位存在前面比较好,容易进位。如果个位存在后面,前面产生进位,就需要整体后移。

http://ybt.ssoier.cn:8088/problem_show.php?pid=1168

求两个不超过200位的非负整数的和。

【输入】

有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。

【输出】

一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。

【输入样例】

22222222222222222222
33333333333333333333

【输出样例】

55555555555555555555
#include <iostream>
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;

}

3. 高精度减法

http://ybt.ssoier.cn:8088/problem_show.php?pid=1169

【题目描述】

求两个大的正整数相减的差。

【输入】

共2行,第1行是被减数a,第2行是减数b(a > b)。每个大整数不超过200位,不会有多余的前导零。

【输出】

一行,即所求的差。

【输入样例】

9999999999999999999999999999999999999
9999999999999

【输出样例】

9999999999999999999999990000000000000
#include <iostream>
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;
}

4. 高精度乘法

c[i] 与 a[i]*b[j]的乘积、进位、原来的c[i]有关

#include <iostream>
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;
}

5. 高精度除法

高精度除以低精度

做除法时,每一次的商的值都在0~9,每次求得的余数连接以后的若干位得到的新的被除数,继续做除法。因此,在做高精度除法时,要涉及到乘法运算和减法运算,还有移位处理。

当然为了程序简洁,可以避免高精度乘法,用0~9次循环减法取代商的值。

这里,我们讨论一下高精度数除以当精度数的结果,采取的方法是按位相除法。

#include <iostream>
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;
 }

实质上,在做高精度数运算的时候,存储高精度数的数组元素可以不仅仅只保留一位数字,而可以采取保留多位数,这样,在做运算,特别是乘法运算时,可以减少很多操作。

高精度除以高精度

用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数。

有点难。暂且放下

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值