分治算法:大整数相乘 字符串实现

由于网上大部分用分治算法实现的大整数相乘程序,其输入乘数竟然设定为int值,实现了分治思想,但实在不能称其为大整数。本文实现了用字符串存储乘数,并且输出正确结果。由于算法未经过大量数据测试,可能还存在问题,欢迎指教讨论,求轻踩。。。

算法分析:https://www.cnblogs.com/little-kwy/archive/2017/09/30/7613642.html

C++代码:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

string cut(string s) { //截取一个字符串前面多余的0 
	int i = 0, length = s.length();
	for (i = 0; i < length-1; i++)
		if (s[i] != '0') 
			break;
	s = s.substr(i, length);
	return s;
}

string add(string a, string b) { //加法,a,b均为正值 
	string s;
	a = cut(a);
	b = cut(b);
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());
	int count = 0, num, t, max_length, a_length = a.length(), b_length = b.length();
	max_length = a_length;
	if (max_length < b_length) max_length = b_length;
	t = 0;
	while (count < max_length) {
		num = 0;
		if (count < a_length) num += (a[count]-'0');
		if (count < b_length) num += (b[count]-'0');
		s += (t+num)%10+'0';
		t = (t+num)/10;		
		count++;
	}
	while (t != 0) {
		s += (t%10)+'0';
		t /= 10;
	}
	reverse(s.begin(), s.end());
	return s;
}

string sub(string a, string b) { //减法,a,b均为正值,且a一定大于等于b 
	string s;
	a = cut(a);
	b = cut(b);
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());
	int count = 0, num, max_length, b_length = b.length();
	max_length = b_length;
	while (count < max_length) {
		num = 0;
		if (a[count] >= b[count]) num = a[count]-b[count];
		else {
			num = 10+a[count]-b[count];
			int t = count+1; //向前取位 
			while (a[t] == '0') {
				a[t] = '9';
				t++;
			}
			a[t]--;
		}	
		s += (num+'0');
		count++;
	}
	s += a.substr(count, a.length());
	count = a.length()-1;
	while (s[count] == '0' && count != 0) count--;
	s = s.substr(0,count+1);
	reverse(s.begin(), s.end());
	return s;	
}

string ten_n(string s, int n) { //计算s乘上n个10 
	while (n--) s += '0';
	return s;
}

bool compare(string a, string b) { //判断a、b绝对值的大小,b大返回0,否则返回1 
	if (a[0] == '-') a = a.substr(1,a.length());
	if (b[0] == '-') b = b.substr(1,b.length());
	if (a.length() > b.length()) return 1;
	else if (a.length() < b.length()) return 0;
	else {
		int count = a.length();
		for (int i = 0; i < count; i++) {
			if (a[i] > b[i]) return 1;
			else if (a[i] < b[i]) return 0;
		}
		return 1;
	}
}

string expand_first(string a, string b, string c) { //拓展函数1,避免代码重用 
	string s = add(b,c);
	a = a.substr(1,a.length());
	if (compare(s,a) == 1) s = sub(s,a);
	else s = '-' + sub(a,s);
	return s;
}

string expand_second(string a, string b, string c) { //拓展函数2,避免代码重用 
	string s;
	b = b.substr(1,b.length());
	c = c.substr(1,c.length());
	s = add(b,c);
	if (compare(a,s) == 1) s = sub(a,s);
	else s = '-' + sub(s,a);
	return s;
}

string add_three_number(string a, string b, string c) { //输入三个数,求和,要考虑正负值的情况 
	if (a[0] != '-' && b[0] != '-' && c[0] != '-') return add(add(a,b),c);
	else if (a[0] == '-' && b[0] != '-' && c[0] != '-') return expand_first(a,b,c);
	else if (a[0] != '-' && b[0] == '-' && c[0] != '-') return expand_first(b,a,c);
	else if (a[0] != '-' && b[0] != '-' && c[0] == '-') return expand_first(c,a,b);
	else if (a[0] == '-' && b[0] == '-' && c[0] != '-') return expand_second(c,a,b);
	else if (a[0] == '-' && b[0] != '-' && c[0] == '-') return expand_second(b,a,c);
	else if (a[0] != '-' && b[0] == '-' && c[0] == '-') return expand_second(a,b,c);
	else return '-'+add(add(a,b),c);
}

string mult(string X, string Y, int n) {
	int flag = 1, note = 0;
	
	string S;
	if (X[0] == '-') {
		flag = flag * (-1);
		X = X.substr(1, X.length());
	} 
	if (Y[0] == '-') {
		flag = flag * (-1);
		Y = Y.substr(1, Y.length()); 
	}
	for (int i = 0; i < n; i++)  //由于一开始输入可能会补0,加上此判断 
		if (X[i] != '0') {
			note++; break;
		}
	for (int i = 0; i < n; i++) 
		if (Y[i] != '0') {
			note++; break;
		}	
	if (note != 2) 
		return "0";
	else if (n == 1) {
		int num = (X[0]-'0')*(Y[0]-'0');
		while (num != 0) {
			S += (num%10+'0');
			num /= 10;
		}
		reverse(S.begin(), S.end());
		if (flag == 1) return S;
		else {
			S = '-' + S;
			return S;
		}	
 	} else {
		string A,B,C,D,E,F,m1,m2,m3;
		A = X.substr(0, n/2);
		B = X.substr(n/2, n);
		C = Y.substr(0, n/2);
		D = Y.substr(n/2, n);
	//	cout << A << ' ' << B << ' ' << C << ' ' << D << endl;
		m1 = mult(A, C, n/2);
		if (compare(A,B) == 1) E = sub(A,B); //由于要判断数的正负,而函数的功能有限,特此分解开来求解 
		else E = '-' + sub(B,A);
		if (compare(D,C) == 1) F = sub(D,C);
		else F = '-' + sub(C,D);
		m2 = mult(E, F, n/2);
		m3 = mult(B, D, n/2);
		S = add_three_number(ten_n(m1, n), ten_n(add_three_number(m1, m2, m3), n/2), m3);
		if (flag == 1) return S;
		else {
			S = '-' + S;
			return S;
		}
	}
}

int main() {
	string X, Y;
	int n, dis, max_length, x_length, y_length;
	while (cin >> X >> Y, X != "-1") { //自动生成n算了.... 
		n = 2;
		x_length = X.length(), y_length = Y.length(); 
		x_length > y_length ? max_length = x_length : max_length = y_length;
		while (n < max_length) n = n * 2;
		while (x_length < n) {
			x_length++;
			X = '0' + X;
		}
		while (y_length < n) {
			y_length++;
			Y = '0' + Y;
		}
 		cout << mult(X,Y,n) << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40571331/article/details/83933127