分治——大整数乘法

第一次自己完整写对,多多指教

算法思路:分治。

第一步:经过预处理将两个整数变为长度一样的两个数(短的在前面补0)

第二部:把两个大整数都平分为前后两部分

第三部:按以下公式计算

(实现大数乘法之前实现了大数加减法)

公式:

X=A*10^(n/2)+B

Y=C*10^(n/2)+D

XY=AC*10^n+((A-B)(D-C)+AC+BD)*10^(n/2)+BD

 

#include<iostream>
#include<string>
#include<algorithm>
#include<assert.h>
using namespace std;


class BigIntegerCalculate {
private:
	static void checkNumber(string numb) {
		assert(!numb.empty());
		int len = numb.length();
		int i = 0;
		if (len == 1 && numb[0] == '-') assert(false);
		if (numb[0] == '-') i++;
		for (; i<len; i++) {
			if (!(numb[i] >= '0'&&numb[i] <= '9'))
				assert(false);
		}
	}
	static void wipeOffFZERO(string& numb) {
		string::iterator it = numb.begin();
		if (numb[0] == '-') it++;
		for (; it != numb.end();)
			if (*it != '0')break;
			else it = numb.erase(it);
			if (numb.length() == 0)numb = "0";
	}
	static void mulInit(string& numb1, string& numb2) {
		int len1 = numb1.length();
		int len2 = numb2.length();
		if (numb1[0] == '-') len1--;
		if (numb2[0] == '-') len2--;
		if (len1 == len2) return;
		string temp = "";
		if (len1>len2)
		{
			if (numb2[0] == '-')
			{
				temp.push_back('-');
				numb2 = numb2.substr(1, string::npos);
			}
			for (int i = 0; i<len1 - len2; i++)
				temp.push_back('0');
			numb2 = temp + numb2;
		}
		else {
			if (numb1[0] == '-')
			{
				temp.push_back('-');
				numb1 = numb1.substr(1, string::npos);
			}
			for (int i = 0; i<len2 - len1; i++)
				temp.push_back('0');
			numb1 = temp + numb1;
		}


	}
	static string add(string numb1, string numb2) {
		wipeOffFZERO(numb1);
		wipeOffFZERO(numb2);
		if (numb1[0] == '-')
		{
			numb1 = numb1.substr(1, string::npos);
			return sub(numb2, numb1);
		}
		if (numb2[0] == '-')
		{
			numb2 = numb2.substr(1, string::npos);
			return sub(numb1, numb2);
		}


		string result = "";
		int len1 = numb1.length();
		int len2 = numb2.length();
		int i = len1 - 1, j = len2 - 1, up = 0;
		for (; i >= 0 && j >= 0; --i, --j) {
			int t = numb1[i] - '0' + numb2[j] - '0' + up;
			result.push_back(t % 10 + '0');
			up = t / 10;
		}
		for (; i >= 0; --i) {
			int t = numb1[i] - '0' + up;
			result.push_back(t % 10 + '0');
			up = t / 10;
		}
		for (; j >= 0; --j) {
			int t = numb2[j] - '0' + up;
			result.push_back(t % 10 + '0');
			up = t / 10;
		}
		if (up != 0) result.push_back(up + '0');


		reverse(result.begin(), result.end());
		return result;
	}
	static string sub(string numb1, string numb2) {
		wipeOffFZERO(numb1);
		wipeOffFZERO(numb2);
		if (numb1[0] == '-')
		{
			numb1 = numb1.substr(1, string::npos);
			return '-' + add(numb2, numb1);
		}
		if (numb2[0] == '-')
		{
			numb2 = numb2.substr(1, string::npos);
			return add(numb1, numb2);
		}


		string result = "";
		int sign = 1;
		int len1 = numb1.length();
		int len2 = numb2.length();
		string left = numb1, right = numb2;
		if (len1<len2 || len1 == len2&&numb1.compare(numb2)<0) {
			left = numb2, right = numb1, sign = -1;
			int t = len1;
			len1 = len2;
			len2 = t;
		}
		int i = len1 - 1, j = len2 - 1, down = 0;
		for (; i >= 0 && j >= 0; --i, --j) {
			int t = left[i] - right[j] - down;
			down = 0;
			while (t<0) {
				down++;
				t += 10;
			};
			result.push_back(t + '0');
		}
		for (; i >= 0; --i) {
			int t = left[i] - down - '0';
			down = 0;
			while (t<0) {
				down++;
				t += 10;
			};
			result.push_back(t + '0');
		}
		for (; j >= 0; --j) {
			int t = right[i] - down - '0';
			down = 0;
			while (t<0) {
				down++;
				t += 10;
			};
			result.push_back(t + '0');
		}


		reverse(result.begin(), result.end());
		if (sign == -1)
			result = '-' + result;
		wipeOffFZERO(result);
		return result;
	}
	static void TZERRO(string& numb) {
		int len = numb.length();
		int i = 0;
		if (numb[0] == '-') i++;
		for (; i<len; i++)
			if (numb[i] != '0') return;
		numb = "0";
	}
	static void Transposition(string& numb, int pos) {
		for (int i = 0; i<pos; i++)
			numb.push_back('0');
	}
	static string mul(string numb1, string numb2) {
		TZERRO(numb1); TZERRO(numb2);
		if (numb1 == "0" || numb2 == "0") return "0";
		mulInit(numb1, numb2);
		int len = numb1.length();
		int a = 1, b = 1;
		if (numb1[0] == '-') { a = -1; len--; numb1 = numb1.substr(1, string::npos); }
		if (numb2[0] == '-') { b = -1, numb2 = numb2.substr(1, string::npos); }
		int sign = a*b;
		string result = "";
		if (len == 1) {
			int t = (numb1[0] - '0')*(numb2[0] - '0');
			result.push_back(t % 10 + '0');
			if (t / 10 != 0) result = char(t / 10 + '0') + result;
		}
		else {
			string A = numb1.substr(0, len / 2);
			string B = numb1.substr(len / 2, string::npos);
			string C = numb2.substr(0, len / 2);
			string D = numb2.substr(len / 2, string::npos);


			string AC = mul(A, C);
			string BD = mul(B, D);
			string AsubB = sub(A, B);
			string DsubC = sub(D, C);


			string M = mul(AsubB, DsubC);
			M = add(M, AC);
			M = add(M, BD);


			Transposition(AC, 2 * (len - len / 2));
			Transposition(M, len - len / 2);


			result = add(AC, M);
			result = add(result, BD);
		}


		if (sign == -1)
			result = '-' + result;


		return result;
	}
public:
	static string Add(string numb1, string numb2) {
		checkNumber(numb1);
		checkNumber(numb2);
		return add(numb1, numb2);
	}
	static string Sub(string numb1, string numb2) {
		checkNumber(numb1);
		checkNumber(numb2);
		return sub(numb1, numb2);
	}
	static string Mul(string numb1, string numb2) {
		checkNumber(numb1);
		checkNumber(numb2);
		return mul(numb1, numb2);
	}
};




int main() {
	string numb1, numb2;
	cin >> numb1 >> numb2;
	cout << BigIntegerCalculate::Mul(numb1, numb2) << endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值