1. 程式人生 > >C/C++高精度運算(大整數運算)詳解(含壓位)

C/C++高精度運算(大整數運算)詳解(含壓位)

1.高精度加法

1.1 高精度加法

        高精度運算的基本運算就是加和減。和算數的加減規則一樣,模擬豎式計算,考慮錯位運算與進位處理。下面是我老師給的程式碼,目前比網上其他的程式碼要精簡和巧妙。
#include <cstdio>
#include <cstring>
int main()
{
	char a[202]={0}, b[202]={0};
	scanf("%s%s", a, b);
	int alen = strlen(a), blen = strlen(b), t = 0, i;
	int a1[202]={0}, b1[202]={0};
	for (i = 0; i < alen; i++)	a1[i] = a[alen-1-i]-'0';
	for (i = 0; i < blen; i++)	b1[i] = b[blen-1-i]-'0';
	alen = (alen > blen) ? alen : blen;
	for (i = 0; i <= alen; i++)
	t = a1[i]+b1[i], a1[i] = t%10, a1[i+1] += t/10;
	while (!a1[i] && i) i--;
	for(; i >= 0; i--) printf("%d", a1[i]);
    return 0;
}

1.2高精度加法(壓位)

        int型可以存9位數字,而上述程式碼在陣列的每個元素中只存了0-9中的一位數,可以說浪費了很多空間,而且計算機計算4+5和3333+4444用的時間是相同的,所以我們有時候用壓位來節省空間和時間。其原理如下:

  • 從鍵盤讀入大整數並存放在字元陣列
  • 從後向前每八位數字存放在一個int型陣列的一個元素
  • 對倆個數組的對應元素進行加減運算,有進位要進位,最後輸出

以下是我老師給的程式碼:

#include <iostream>
#include <cstring>
#include <cstdio> 
using namespace std;
const int INF = 1E8;
struct Data{
	int u[50], l;
	Data(){
		memset(u, 0, sizeof(u)), l = 0;
	}
	void change(string a){
		int len = a.size(), k = len / 8, i = 0;
		l = k + (len%8 > 0);
		for (len; len > 8; len -= 8)
			sscanf(a.substr(len-8, 8).c_str(), "%d", &u[i++]);//註釋一
		if (len > 0) sscanf(a.substr(0, len).c_str(), "%d", &u[i]);
	}
	void print(){
		int k = l-1;
		printf("%d", u[k--]);
		while (k >= 0) printf("%8.8d", u[k--]);//註釋二
		printf("\n");
	}
}a, b;
int main(){
	string aa, bb, ac;
	cin >> aa >> bb;
	int ka = 0, kb = 0, i;
	a.change(aa), b.change(bb);
	for (i = 0; i < 50; i++)
		a.u[i] += b.u[i], a.u[i+1] += a.u[i] / INF, a.u[i] %= INF;
	for (i = 49; a.u[i]==0 && i>0; i--);
	a.l = i + 1;
	a.print();
	return 0;
}

2.高精度減法

2.1 高精度減法

        原理和加法一樣,需要不過考慮的不是進位,而是借位

程式碼如下:

#include <cstdio>
#include <cstring>
int main()
{
	char a[202]={0}, b[202]={0};
	scanf("%s%s", a, b);
	int alen = strlen(a), blen = strlen(b), t = 0, i;
	int a1[202]={0}, b1[202]={0};
	for (i = 0; i < alen; i++)	a1[i] = a[alen-1-i]-'0';
	for (i = 0; i < blen; i++)	b1[i] = b[blen-1-i]-'0';
	alen = (alen > blen) ? alen : blen;
	for (i = 0; i <= alen; i++)
	t = a1[i]-b1[i], t<0?(t+=10,a1[i+1]--):t, a1[i] = t;
	while (!a1[i] && i) i--;
	for(; i >= 0; i--) printf("%d", a1[i]);
    return 0;
}

2.2 高精度減法(壓位)

        減法和加法大同小異,如果你會了加法,那麼減法也不足為懼。以下程式碼是我自己寫的,和我老師寫的有一定差距,如有不足請指出。

#include <iostream>
#include <cstring>
#include <cstdio> 
using namespace std;
const int INF = 1E8;
struct Data{
	int u[50], l;
	Data(){
		memset(u, 0, sizeof(u)), l = 0;
	}
	void change(string a){
		int len = a.size(), k = len / 8, i = 0;
		l = k + (len%8 > 0);
		for (len; len > 8; len -= 8)
			sscanf(a.substr(len-8, 8).c_str(), "%d", &u[i++]);
		if (len > 0) sscanf(a.substr(0, len).c_str(), "%d", &u[i]);
	}
	void print(){
		int k = l-1;
		printf("%d", u[k--]);
		while (k >= 0) printf("%8.8d", u[k--]);
		printf("\n");
	}
}a, b;
int main(){
	string aa, bb, ac;
	cin >> aa >> bb;
	int ka = 0, kb = 0, i,t;
	a.change(aa), b.change(bb);
	for (i = 0; i < 50; i++)
		t = a.u[i] - b.u[i],(t < 0)?(t+=INF,a.u[i+1]--):t,a.u[i] = t; 
	for (i = 49; a.u[i]==0 && i>0; i--);
	a.l = i + 1;
	a.print();
	return 0;
}
以上的倆個程式碼都只能當且僅當a>=b時才能正常工作,望注意。

3.高精度乘法

3.1 高精度乘法

        這個方法出自吳永輝老師。此程式碼簡直讓我拍手叫絕。

原理如下:

                        3    2    1    0                    ——>陣列a、b的下標

                        3    4    5    6       i            ——>陣列a[]

                    *  1    2    7    8       j            ——>陣列b[]

               ————————————

                 2    7    6    4    8 

            2    4    1    9    2

            6    9    1    2

      3    4    5    6

——————————————————

      4    4    1    6    7    6    8                ——>陣列c[]

      6    5    4    3    2    1    0        i+j    ——>陣列c的下標

以上是倆個四位數相乘的豎式計算方法。可以看出,數的右面對齊,從低位向高位計算,計算結束後將一列結果相加即為答案。那麼把倆個數從右向左依次標記為0、1、2...n,那麼每一列的結果就是第一個數的下標為i的數與第二個數的下標為j的數相乘的結果,其存放在第i+j列。最終結果是每一列相加,就是i+j這一列所有數相加。所以可以用c[i+j] += a[i]*b[j]。

for(int i = 0;i < LA-1;i++)
for(int j = 0;j < LB-1;j++)
	c[i+j] += a[i]*b[j];
for(int i = 0;i < LA+LB;i++)
if(c[i] >= 10){
	c[i+1] += c[i]/10;
	c[i] %= 10; 
}

3.2 高精度乘法(壓位)