【算法】大整数乘法

大整数乘法

问题描述

求两个不超过200位的非负整数的积。

输入形式

有两行,每行是一个不超过200位的非负整数,没有多余的前导0。

输出形式

一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。

样例输入

1234567890

9876543210

样例输出

12193263111263526900

 

解题思路:

1     :采用了数组的形式进行计算。将输入的值以字符的形式存到数组中取,再转化成整数形式相乘。
2.    根据课本的描述采用分治的方法求解。主要部分是递归的不同种情况。当n=2时直接求解,当n>2,则对其进行分治。按照公式:A*B=a1*b1*10^n+[(a1+a0)*(b0+b1)-a1*a0-b1*b0]*10^n/2+a0*b0求解
 

#include<iostream>
#include<cstring>
using namespace std;
int main(){
	char A[200],B[200];
	int  X[200],Y[200];
	int Z[401]={0};
	cin>>A;
	cin>>B;
	int lenA = strlen(A);
	int lenB = strlen(B);
    int i,j;
    for(i=lenA-1,j=0;i>=0;i--)
    {
        X[j]=A[i]-'0';
        j++;
    }
    for(i=lenB-1,j=0;i>=0;i--)
    {
        Y[j]=B[i]-'0';
        j++;
    }
    for(i=0;i<lenA;i++)
    {
        for(j=0;j<lenB;j++)
            Z[i+j]=Z[i+j]+X[i]*Y[j];
    }
    for(i=0;i<400;i++)
    {
        if(Z[i]>=10)
        {

            Z[i+1]=Z[i+1]+Z[i]/10;
            Z[i]=Z[i]%10;
        }
    }
    
    for(i=400;i>0;i--)
    {
        if(Z[i]==0)     continue;
        else    break;
    }
	for(;i>=0;i--)
		cout<<Z[i];
	return 0;
}

第二种:

#include<iostream>
#include<string>
#include<algorithm>
#include<sstream>
using namespace std;
//string转换为int
int str_to_int(string s) {
	int num;
	stringstream ss(s);
	ss >> num;
	return num;
}
//int转换为string
string int_to_str(int num) {
	string s;
	stringstream ss;
	ss << num;
	ss >> s;
	return s;
}
//前置0 ,因为大数的长度必须要为2^n的倍数,才能划分
//去掉前置零,substr()复制子字符串 
void removePrezero(string &s) {
	int i = 0;
	while (i < s.length() && s[i] == '0') //过滤前置零 
		i++;
	if (i < s.length())		s = s.substr(i);    //复制剩余子字符串 
	else	s = "0";
}
//大数相加
string add(string s1, string s2) {
	string s = "";
	//去掉前置0
	removePrezero(s1);	
	removePrezero(s2);
	//先把字符串颠倒,方便相加
	reverse(s1.begin(), s1.end()); 
	reverse(s2.begin(), s2.end());
	int c = 0;  //记录进位值 
	for (int i = 0;c|| i < max(s1.length(), s2.length()); i++) {
		int t = c;
		if (i < s1.length())	t += s1[i] - '0';
		if (i < s2.length())	t += s2[i] - '0';
		int d = t % 10;
		s = char(d + '0') + s;	
		c = t / 10;
	}
	return s;	
} 
//大数相减
string sub(string &s1, string &s2) {
	string s = "";
	string flag;
	//去掉前置0
	removePrezero(s1);	
	removePrezero(s2);
	//求长比较,确定正负 
	int len1 = s1.length();
	int len2 = s2.length();
	int len = len1>len2 ? len1 : len2;	
	if (len1 < len2)flag = "-";
	else if (len1 > len2)flag = "+";
	else {    //s.at(n)  返回s中下标为n的元素 
		int i;
		for (i = 0; i < len1; i++) {
			if (s1.at(i) > s2.at(i)) {
				flag = "+";	 break;
			}
			else if (s1.at(i) < s2.at(i)) {
				flag = "-"; break;
			}
		}
		if (i == len1)s == "0";
	}
	int* num = (int*)malloc(sizeof(int)*len);
	reverse(s1.begin(), s1.end());	
	reverse(s2.begin(), s2.end());
	int c = 0;	//记录结果位数 
	for (int i = 0; i < len; i++) {
		int n1 = i < len1 ? s1[i] - '0' : 0;
		int n2 = i < len2 ? s2[i] - '0' : 0;
		if (flag == "+")	num[c++] = n1 - n2;
		else num[c++] = n2 - n1;
	}
	for (int j = 0; j < c; j++) {
		if (num[j] < 0) {
			num[j] += 10; num[j + 1] -= 1;
		}
	}
	c--;
	//去除可能存在的前置零 
	while (num[c] == 0)c--;
	for (int j = 0; j <=c; j++){
		s = char(num[j] + '0') + s ;
	}
	if (flag == "-")return flag + s;
	else return s;
}
//增加前置0
void addPrezero(string &s, int L) {
	for (int i = 0; i < L; i++)
		s = s.insert(0, "0");
}
//增加后置0,大数*10^n	相当于在数的后面加n个0
string addLastzero(string s, int L) {
	string s1 = s;
	for (int i = 0; i < L; i++)
		s1 += "0";
	return s1;
}
//大数相乘
string mult(string &s1, string &s2) {
	bool flag1 = false, flag2 = false;	
	string sign;	//记录结果正负	 
	if (s1.at(0) == '-') {
		flag1 = true; s1 = s1.substr(1);
	}
	if (s2.at(0) == '-') {
		flag2 = true; s2 = s2.substr(1);
	}
	if (flag1 || flag2) sign = "-";
	else sign = "+";
	int L = 4; 
	//前置若干个0,使长度为2^n的倍数	
	if (s1.length() > 2 || s2.length() > 2) {
		if (s1.length() >= s2.length()) {
			while (L < s1.length())		L *= 2;
			if (L != s1.length()) 
		    addPrezero(s1, L - s1.length());
			addPrezero(s2, L - s2.length());				          
		}
		else {
			while (L < s2.length())L*=2;
			if (L != s2.length())
			addPrezero(s2, L - s2.length());
			addPrezero(s1, L - s1.length());
		}
	}
	if (s1.length() == 1)addPrezero(s1, 1);
	if (s2.length() == 1)addPrezero(s2, 1);
 	//进行运算 
	int n = s1.length();
	string result, a0, a1, b0, b1;
	if (n > 1) {	//大于1取n/2 
		a1 = s1.substr(0, n / 2);
		a0 = s1.substr(n / 2, n);
		b1 = s2.substr(0, n / 2);
		b0 = s2.substr(n / 2, n);
	}
	if (n == 2) {	//n==2 计算 
		int x1 = str_to_int(a1);
		int x2 = str_to_int(a0);
		int y1 = str_to_int(b1);
		int y2 = str_to_int(b0);
		int num = (x1 * 10 + x2)*(y1 * 10 + y2);
		result = int_to_str(num);
	}else {		// n!=2 采用公式求解
		//A*B=a1*b1*10^n+[(a1+a0)*(b0+b1)-a1*a0-b1*b0]*10^n/2+a0*b0 
		string c2 = mult(a1, b1);
		string c0 = mult(a0, b0);
		string temp1 = add(a0, a1);
		string temp2 = add(b1, b0);
		string temp3 = add(c2, c0);
		string temp_c1 = mult(temp1, temp2);
		string c1 = sub(temp_c1, temp3);
		string s1 = addLastzero(c1, n / 2);
		string s2 =addLastzero(c2, n);
		result = add(add(s1, s2), c0);
	}
	if (sign == "-")result.insert(0, sign);
	return result;
}
int main() {
	string s1 ,s2;
	cin>>s1>>s2;
	cout << mult(s1, s2);	
}

猜你喜欢

转载自blog.csdn.net/sunshine641/article/details/84496789