关闭

【算法设计与分析基础】大整数乘法string版

标签: 大整数乘法算法乘法
372人阅读 评论(0) 收藏 举报
分类:
#include<iostream>
#include<string>
#include<time.h>
#include<stdlib.h>
#include<sstream>
using namespace std;

class BigDecimal{
private:
	int max(int a,int b){//获取两数中的最大值
		return a^((a^b) & -(a<b));
	}
public:
	string n;
	BigDecimal(){
		n="0";
	}
	void setString(string n){
		this->n=n;
	}
	BigDecimal(string n){
		this->n=n;
	}
	BigDecimal operator + (BigDecimal b){
		string s,l;//s为加数,l为加数
		int temp=0,i,j;//temp记录进位,i用于遍历s,j用于遍历l
		//判断哪个数字更长,长的给s,短的给l
		if(n.length()>=b.n.length()){
			s=n;
			l=b.n;
			i=s.length()-1;
			j=b.n.length()-1;
		}
		else{
			s=b.n;
			l=n;
			i=s.length()-1;
			j=n.length()-1;
		}
		//开始进行加法运算
		while(j>=0){
			s[i]=s[i]+l[j]+temp-48;//两位相加,并加上进位,减去48('0'的ASCII码)
			if(s[i]>'9'){//如果两位相加大于10,就减10,然后进位置1
				s[i]-=10;
				temp=1;
			}
			else{
				temp=0;
			}
			i--;
			j--;
		}
		//如果l遍历完后,进位仍然为1,就要消耗进位直到它为0
		while(i>=0 && temp==1){
			s[i]++;
			if(s[i]>=58){
				s[i]-=10;
				i--;
			}
			else{
				temp=0;
				break;
			}
		}
		//如果到达最高位后还有进位,则该数最前面加个'1'
		if(temp){
			s='1'+s;
		}
		return BigDecimal(s);
	}
	BigDecimal operator - (BigDecimal b){
		string S,E;//S是被减数,E是减数
		/**
		 *  由于(a1+a0)*(b1+b0)-(a1*b1+a0*b0) = a1 * b0 + a0 * b1
		 *  所以该减法运算不会为负数
		 */
		S=n;
		E=b.n;
		int i=S.length()-1,j=b.n.length()-1,temp=0;

		// 开始进行减法运算
		while(j>=0){
			S[i]=S[i]+48-E[j]-temp;//两位相减,减去借位,加上48
			if(S[i]<'0'){//如果不够减,加10,借位置1
				S[i]+=10;
				temp=1;
			}
			else{
				temp=0;
			}
			i--;
			j--;
		}
		//减完后如果借位仍然为1,消耗借位直到为0
		while(i>=0 && temp){
			S[i]--;
			if(S[i]<'0'){
				S[i]+=10;
				temp=1;
			}
			else{
				temp=0;
			}
		}
		i=0;
		//如果数字开头为0,就除去
		while(S.length() > 1){
			if(S[i]=='0'){
				S.erase(0,1);
			}
			else{
				break;
			}
		}
		return BigDecimal(S);
	}
	BigDecimal mul(string a,string b){
		// int与int相乘
		int num = atoi(a.c_str()) * atoi(b.c_str());
		if(num==0)return BigDecimal();
		string s;
		stringstream ss;
		ss<<num;
		ss>>s;
		return BigDecimal(s);
	}


	BigDecimal mul(string a,int n){
		if(a=="0"){
			return BigDecimal();
		}
		char *k=new char[n+1];
		memset(k,'0',n*sizeof(char));
		k[n]='\0';
		string temp;
		a.append(k);
		delete[]k;
		return BigDecimal(a);
	}
	void sub(int center,BigDecimal *s1,BigDecimal *s0){
		if(n.length()<=center){//如果该大整数没有足够的长度被分为两半
			/**
			 * 那 a1=0      a0=n
			 */
			s0->n=n.substr(0,n.length());
		}
		else{
			/**
			 *  否则就分成两半
			 */
			s0->n=n.substr(n.length()-center,center);
			s1->n=n.substr(0,n.length()-center);
		}
	}
	BigDecimal operator * (BigDecimal b){
		//如果数组长度小于等于4,直接调用原始乘法
		if(n.length()<=4 && b.n.length()<=4){
			return mul(n,b.n);
		}
		BigDecimal temp , a1 , a0 , b1 , b0 , c2 , c1 , c0;
		int maxBit=max(n.length() , b.n.length());
		sub(maxBit/2 , &a1 , &a0);
		b.sub(maxBit/2 , &b1 , &b0);
		c2 = a1 * b1;
		c0 = a0 * b0;
		c1 = (a1 + a0) * (b1 + b0) - (c2 + c0);
		return mul(c2.n , maxBit/2*2) + mul(c1.n , maxBit/2) + c0;
	}
};

int main(){
    clock_t start , finish;
    double totaltime;
	srand((unsigned int)time(0));
	int Bit=10;//这里修改两个大整数的位数
	int pos=1;
	int i,j;
	string s,m;
	cout<<Bit<<" : "<<endl;
	do{
		j=rand()%10+48;
	}
	while(j=='0');
	s+=(char)j;
	for(i=0;i<Bit-1;i++){
		j=rand()%10+48;
		s+=(char)j;
	}
	do{
		j=rand()%10+48;
	}
	while(j=='0');
	m+=(char)j;
	for(i=0;i<Bit-1;i++){
		j=rand()%10+48;
		m+=(char)j;
	}
	cout<<s<<" * "<<m<<" = "<<endl;
	BigDecimal a(s),b(m),c;
	start=clock();
	c=a * b;
	finish=clock();
	cout<<c.n<<endl;
	totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"此程序的运行时间为"<<totaltime<<"秒!"<<endl;
   return 0;
}


如果需要更快一点的话需要自己编写一个原始乘法,然后

BigDecimal operator * (BigDecimal b){
//如果数组长度小于等于4,直接调用原始乘法
if(n.length()<=4 && b.n.length()<=4){
return mul(n,b.n);
}
BigDecimal temp , a1 , a0 , b1 , b0 , c2 , c1 , c0;
int maxBit=max(n.length() , b.n.length());
sub(maxBit/2 , &a1 , &a0);
b.sub(maxBit/2 , &b1 , &b0);
c2 = a1 * b1;
c0 = a0 * b0;
c1 = (a1 + a0) * (b1 + b0) - (c2 + c0);
return mul(c2.n , maxBit/2*2) + mul(c1.n , maxBit/2) + c0;
}

中修改

if(n.length()<=4 && b.n.length()<=4){
return mul(n,b.n);
}

中的4为600,然后改mul(n,b.n)为你的原始乘法函数mul(string,string)

大整数算法讲解与分析ppt:http://download.csdn.net/detail/u013580497/8888515

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:62348次
    • 积分:1410
    • 等级:
    • 排名:千里之外
    • 原创:80篇
    • 转载:6篇
    • 译文:1篇
    • 评论:15条
    最新评论