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

原创 2015年07月10日 20:17:48
#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

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

算法设计与分析:第三章 分治 3.3二进制大整数的乘法

/* 二进制大整数的乘法: 请设计一个有效的算法,可以进行两个n 位二进制大整数的乘法运算 设x = 3141, A = 31 B=41 y = 5327, C = 53,D=27 x*y ...

008-大整数乘法-分治法-《算法设计技巧与分析》M.H.A学习笔记

设u和v是两个n位二进制整数,传统乘法算法需要Θ(n2)的时间来计算u和v的乘积。 但我们还有一个Θ(n1.59)的改进算法。

【算法与设计分析基础】大整数乘法int[]版+分治法求幂

大整数乘法int[]版+分治法求幂

009-矩阵乘法-分治法-《算法设计技巧与分析》M.H.A学习笔记

A、B是两个n*n的矩阵,计算C=A*B。

计算机算法设计与分析作业01:分治法求解大数乘法+L型骨牌的棋盘覆盖问题

计算机算法设计与分析作业01:分治法求解大数乘法+L型骨牌的棋盘覆盖问题 1. 2.L型骨牌的棋盘覆盖问题: 代码实现: #include #include #include ...

001-整数快速幂-归纳法-《算法设计技巧与分析》M.H.A学习笔记

计算x的n次幂的朴素算法复杂度为O(N),我们还有一种复杂度为O(log N)的快速幂方法。

【算法设计与分析】1、整数划分问题

#include using namespace std; /* void show(int *put, int len) //一个输出函数 { for(int i=0 ; i < len ;...

算法设计与分析:第三章 分治 3.2正整数划分

/* 将正整数n表示成一系列正整数之和: n = n1 + n2 + ... +nk 其中n1>=n2>=...>=nk>=1,k>=1 正整数的这种表示称为正整数n的划分。求正整数n的不同划分个数 ...

算法设计与分析基础(第3版)读书笔记(及几处翻译上的错误~~)

算法设计与分析基础(第3版) p16 in-place翻译为‘在位’?‘就地’更合适点p38 amortized应翻译为‘均摊’,‘摊销’这个词简直莫名其妙(可能因为翻译是做算法...
  • cteng
  • cteng
  • 2015-02-02 11:19
  • 1120
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)