1. 程式人生 > >[C++]高精度演算法

[C++]高精度演算法

目錄

高精度加法    高精度減法    高精度乘法    高精度除法    高精度階乘


高精度加法

用程式來模擬豎式加法即可,注意在輸出的時候除去多餘的前導零。

程式程式碼

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX_SIZE = 3333;
inline void High_precision_Addition(int *a, int *b, int *c) {
	c[0] = 1; int x = 0;
	while (c[0] <= a[0] || c[0] <= b[0]) {
		c[c[0]] = a[c[0]] + b[c[0]] + x;
		x = c[c[0]] / 10;
		c[c[0]] %= 10;
		++c[0];	
	};
	c[c[0]] = x;
	while (c[c[0]] == 0 && c[0] > 1) --c[0];	
};
int main(int argc, char *argv[]) {
	char str1[MAX_SIZE], str2[MAX_SIZE];
	cin >> str1 >> str2;
	int a[MAX_SIZE], b[MAX_SIZE], c[MAX_SIZE];
	memset(a, 0, sizeof a); memset(b, 0, sizeof b); memset(c, 0, sizeof c);
	a[0] = strlen(str1); b[0] = strlen(str2);
	for (int i = 0; i < a[0]; ++i) a[a[0] - i] = str1[i] - '0'; 
	for (int i = 0; i < b[0]; ++i) b[b[0] - i] = str2[i] - '0';
	High_precision_Addition(a, b, c);
	for (int i = c[0]; i >= 1; --i) printf("%d", c[i]); cout.put('\n'); //和
	return 0;	
};

高精度減法

用程式來模擬豎式減法即可,與高精度加法類似,不過得考慮被減數與減數的大小關係還得考慮借位,所以程式碼相對於高精度加法更為複雜。

程式程式碼

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX_SIZE = 3333;
inline bool Is_swap(char *__x_, char *__y_) {
	char Mid_Element[MAX_SIZE];
	if ((strlen(__x_) < strlen(__y_)) || (strlen(__x_) == strlen(__y_) && strcmp(__x_, __y_) < 0)) {
		strcpy(Mid_Element, __x_);
		strcpy(__x_, __y_);
		strcpy(__y_, Mid_Element);
		return true;
	};	
	return false;
};
inline void High_precision_Subtraction(int *a, int *b, int *c) {
	 c[0] = 1;
	while (c[0] <= a[0] || c[0] <= b[0]) {
		if (a[c[0]] < b[c[0]]) {
			a[c[0]] += 10;
			--a[c[0] + 1];	
		};
		c[c[0]]	= a[c[0]] - b[c[0]];
		++c[0];
	};
	while (c[c[0]] == 0 && c[0] > 1) --c[0];
};
int main(int argc, char *argv[]) {
	char str1[MAX_SIZE], str2[MAX_SIZE];
	cin >> str1 >> str2; bool flag = Is_swap(str1, str2);
	int a[MAX_SIZE], b[MAX_SIZE], c[MAX_SIZE];
	memset(a, 0, sizeof a); memset(b, 0, sizeof b); memset(c, 0, sizeof c);
	a[0] = strlen(str1); b[0] = strlen(str2);
	for (int i = 0; i < a[0]; ++i) a[a[0] - i] = str1[i] - '0'; 
	for (int i = 0; i < b[0]; ++i) b[b[0] - i] = str2[i] - '0';
	High_precision_Subtraction(a, b, c);
	if (flag == true) cout.put('-');
	for (int i = c[0]; i >= 1; --i) printf("%d", c[i]); cout.put('\n'); //差
	return 0;	
};

高精度乘法

用程式模擬豎式乘法即可,在做乘法運算時,同樣也有進位,同時對每一位進行乘法運算時,必須進行錯位相加。

程式程式碼

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX_SIZE = 3333;
inline void High_precision_Multiplication(int *a, int *b, int *c) {
	int x;
	for (int i = 1; i <= a[0]; ++i) {
		x = 0;
		for (int j = 1; j <= b[0]; ++j) {
			c[i + j - 1] = a[i] * b[j] + x + c[i + j - 1];
			x = c[i + j - 1] / 10;
			c[i + j - 1] %= 10;	
		};
		c[i + b[0]] = x;	
	};
	c[0] = a[0] + b[0];
	while (c[c[0]] == 0 && c[0] > 1) --c[0];
};
int main(int argc, char *argv[]) {
	char str1[MAX_SIZE], str2[MAX_SIZE];
	cin >> str1 >> str2;
	int a[MAX_SIZE], b[MAX_SIZE], c[MAX_SIZE];
	memset(a, 0, sizeof a); memset(b, 0, sizeof b); memset(c, 0, sizeof c);
	a[0] = strlen(str1); b[0] = strlen(str2); 
	for (int i = 0; i < a[0]; ++i) a[a[0] - i] = str1[i] - '0'; 
	for (int i = 0; i < b[0]; ++i) b[b[0] - i] = str2[i] - '0';
	High_precision_Multiplication(a, b, c);
	for (int i = c[0]; i >= 1; --i) cout << c[i]; cout.put('\n'); //積
	return 0;
};

高精度除法

高精度除法一般有高精度除以低精度與高精度除以高精度,前者程式碼較為簡單,後者則作用範圍更加廣闊。高精度除以低精度與前三種高精度演算法類似,都是按位運算;而高精度除以高精度則是以減法來模擬除法。

程式程式碼1

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX_SIZE = 3333;
inline int High_precision_Division(int *a, int b, int *c) {
	int x;
	for (int i = 1; i <= a[0]; ++i) {
		c[i] = (x * 10 + a[i]) / b;
		x = (x * 10 + a[i]) % b;	
	};
	c[0] = 1;
	while (c[c[0]] == 0 && c[0] < a[0]) ++c[0];
    return x;
};
int main(int argc, char *argv[]) {
	char str[MAX_SIZE]; int b; 
	cin >> str >> b;
	int a[MAX_SIZE], c[MAX_SIZE];
	memset(a, 0, sizeof a); memset(c, 0, sizeof c);
	a[0] = strlen(str); 
	for (int i = 0; i < a[0]; ++i) a[i + 1] = str[i] - '0'; 
	int x = High_precision_Division(a, b, c);
	for (int i = c[0]; i <= a[0]; ++i) cout << c[i]; cout.put('\n'); //商
	cout << x << endl; //餘數
	return 0;	
};

程式程式碼2

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
using namespace std;
const int MAX_SIZE = 3333;
inline void Input(int *radix) {
	string str; cin >> str; radix[0] = str.length();
	for (int i = 0; i < radix[0]; ++i) radix[radix[0] - i] = str[i] - '0';	
};
inline void Print(const int *radix) {
    if (radix[0] == 0) {cout << 0 << endl; return;};
	for (int i = radix[0]; i >= 1; --i) printf("%d", radix[i]);
	cout.put('\n'); return;	   	   	
};
inline int Compare(const int *__x_, const int *__y_) {
	if (__x_[0] > __y_[0]) return 1;
	if (__x_[0] < __y_[0]) return -1;
	for (int i = __x_[0]; i >= 1; --i) {
		if (__x_[i] == __y_[i]) continue;
		else if (__x_[i] > __y_[i]) return 1;
		else if (__x_[i] < __y_[i]) return -1;	
	};
	return 0;   	
};
inline void Subtraction(int *__x_, int *__y_) {
	int sign = Compare(__x_, __y_);
	if (sign == 0) {__x_[0] = 0; return;}; 
	if (sign == 1) {	
		for (int i = 1; i <= __x_[0]; ++i) {
			if (__x_[i] < __y_[i]) {
				__x_[i] += 10; --__x_[i + 1];	
			};
			__x_[i] -= __y_[i];	
		};
		while (__x_[__x_[0]] == 0 && __x_[0] > 0) --__x_[0]; return; 	
	};
};
inline void Numcpy(const int *radix, int *pending, int pos) {
	for (int i = 1; i <= radix[0]; ++i) pending[i + pos - 1] = radix[i];
	pending[0] = radix[0] + pos - 1; 
};
inline void High_precision_Division(int *a, int *b, int *c) {
	int sign = Compare(a, b);
	if (sign == -1) {c[0] = 1; c[1] = 0; return;}; 
	if (sign == 1 || sign == 0) { 
		int Temp[MAX_SIZE]; c[0] = a[0] - b[0] + 1;
		for (int i = c[0]; i >= 1; --i) {
			memset(Temp, 0, sizeof Temp); Numcpy(b, Temp, i);
			while (Compare(a, Temp) != -1) {++c[i]; Subtraction(a, Temp);};	
		};
		while (c[c[0]] == 0 && c[0] > 0) --c[0]; return;	
	};
};
int main(int argc, char *argv[]) {
	int a[MAX_SIZE], b[MAX_SIZE], c[MAX_SIZE];
	memset(a, 0, sizeof a); memset(b, 0, sizeof b); memset(c, 0, sizeof c);
	Input(a); Input(b); High_precision_Division(a, b, c);
	Print(c); Print(a); //商與餘數
	return 0;
};	 

高精度階乘

高精度階乘的本質是什麼?實際上就是一個高精度乘法,所以code就很好寫了呀~不過還得做一個小優化來應付幾千甚至幾萬的階乘,要不然按位算的話就妥妥的TLE了呀。

程式程式碼

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX_SIZE = 3333;
inline void High_precision_Factorial(const int N, int *c) {
	c[1] = 1; int x, temp, index = 2;
	for (int i = 2; i <= N; ++i) {
		x = 0;
		for (int j = 1; j <= index - 1; ++j) { //小優化
			temp = c[j] * i + x;
			c[j] = temp % 10;
			x = temp / 10;
		};	
		while (x != 0) {
			c[index++] = x % 10;
			x /= 10;	
		};
	};
	for (int i = MAX_SIZE; i >= 1; --i) if (c[i] != 0) {c[0] = i; break;}; 
};
int main(int argc, char *argv[]) {
	int N; cin >> N;
	int c[MAX_SIZE]; memset(c, 0, sizeof c);
	High_precision_Factorial(N, c);
	for (int i = c[0]; i >= 1; --i) printf("%d", c[i]); cout.put('\n');
	return 0;	
};