高進度算法-補碼運算


orz CYX


針對帶負數的高精度數運算,可以採用補碼錶示法。

補碼錶示法即用原碼錶示正數,補碼錶示負數。


補碼錶示法表示的任何數之間都可以進行加法運算,捨棄了減法,簡化了代碼。

對於乘法運算,先將補碼錶示的負數轉化爲正數,運算之後得到若爲正數,再轉化爲負數。


//補碼高精度算法。
#include
#include
#include

#define R register
#define ll long long
#define base 1000000000
#define dmax(_a,_b)(_a)>(_b)?(_a):(_b)
using namespace std;

struct BigNum
{
	int num[10010],len;		
	void clear()
	{
		memset(num,0,sizeof(num));
		len=1;
	}
	inline void flip()
	{
		R int i;
		for(i=1;i<=len&&!num[i];++i);
		if(i>len)return;
		num[i]=base-num[i];
		for(++i;i<=len;++i)num[i]=base-1-num[i];
		num[len]-=base;
	}
	void scan(const char *ss)
	{
		R int i,j,k,rev=0,cnt=1;
		while(ss[0]<'0'||ss[0]>'9'){if(ss[0]=='-')rev=1;++ss;}
		memset(num,0,sizeof(num));
		for(i=0;ss[i]>='0'&&ss[i]<='9';++i);
		for(j=i-1,k=1;j>=0;--j)
		{
			num[k]+=cnt*(ss[j]-'0');
			cnt=(cnt<<3)+(cnt<<1);
			if(cnt==base)cnt=1,++k;
		}
		if(!num[k])--k;
		len=k;
		if(rev)flip();
	}
	
	void print()
	{
		R int rev=0,i;
		if(num[len]<0)rev=1,flip(),printf("-");
		while(len>1&&!num[len])--len;
		printf("%d",num[len]);
		for(i=len-1;i>=1;--i)
			printf("%09d",num[i]);
		if(rev)flip();
	}
	
	inline BigNum operator + (const BigNum &b1)const
	{
		R BigNum ret;
		ret.clear();
		R int i,flow=0;
		ret.len=dmax(b1.len,len);
		for(i=1;i<=ret.len;++i)
		{
			ret.num[i]=num[i]+b1.num[i]+flow;
			flow=ret.num[i]/base,ret.num[i]%=base;
			while((flow>0||i1&&!num[len])--len;
		if(b1.num[b1.len]<0)b1.flip(),rev2=1;
		while(b1.len>1&&!b1.num[b1.len])--b1.len;
		
		ret.len=len+b1.len;
		for(i=1;i<=len;++i)
			for(j=1;j<=b1.len;++j)
			{
				tmp=ret.num[i+j-1]+(ll)num[i]*b1.num[j];
				ret.num[i+j-1]=tmp%base,ret.num[i+j]+=tmp/base;
			}
		while(ret.len>1&&!ret.num[ret.len])--ret.len;
		if(rev1)flip();
		if(rev2)b1.flip();
		if(rev1^rev2)ret.flip();
		return ret;
	}
};

char q1[10010],s[10010];
struct BigNum q2[2010];
int n;

int main()
{
	R int i,j,k,des;
	R int t1=0,t2=0;
	R BigNum sum;
	scanf("%s",s+1);
	n=strlen(s+1);
	s[0]='(',s[n+1]=')',s[n+2]='\0',++n;
	for(i=0;i<=n;)
	{
		des=-1;
		if((s[i]=='+'||s[i]=='-'||s[i]==')')&&q1[t1]=='*'&&s[i-1]!='*')
		{
			sum.clear(),sum.num[1]=1;
			while(q1[t1]=='*')sum=sum*q2[t2],--t1,--t2;
			sum=sum*q2[t2],q2[t2]=sum;
		}
		if(s[i]==')')
		{
			sum.clear();
			while(q1[t1]!='(')
			{
				if(q1[t1]=='+')sum=sum+q2[t2];
				else q2[t2].flip(),sum=sum+q2[t2];
				--t1,--t2;
			}
			--t1,q2[t2]=sum+q2[t2];
		}
		if( ((s[i]=='-'||s[i]=='+')&&( (s[i+1]>='0'&&s[i+1]<='9' ) || s[i+1]=='-' ||s[i+1]=='+' )) || (s[i]>='0'&&s[i]<='9') )
		{
			if(s[i-1]!='*'&&s[i-1]!='(')q1[++t1]='+';
			q2[++t2].scan(s+i);
			des=i;
			while(s[des]<'0'||s[i]>'9')++des;
			while(s[des]>='0'&&s[des]<='9')++des;
		}else{
			if(s[i]!=')')q1[++t1]=s[i];
			des=i+1;
		}
		if(des!=-1)i=des;
	}
	q2[t2].print();
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章