1. 程式人生 > 其它 >一本通-高精度計算

一本通-高精度計算

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次迴圈減法取代商的值。

這裡,我們討論一下高精度數除以當精度數的結果,採取的方法是按位相除法。