高精度计算大数模板

更新:高效大数模板

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<set>
#include<queue>
using namespace std;

#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
#define arrLen 50050             // 数组长度
class BigNum
{
private:
	int a[arrLen];    //可以控制大数的位数
	int len;       //大数长度
public:
	BigNum(){ len = 1;memset(a,0,sizeof(a)); }   //构造函数
	BigNum(const int);       //将一个int类型的变量转化为大数
	BigNum(const char*);     //将一个字符串类型的变量转化为大数
	BigNum(const BigNum &);  //拷贝构造函数
	BigNum &operator=(const BigNum &);   //重载赋值运算符,大数之间进行赋值运算

	friend istream& operator>>(istream&,  BigNum&);   //重载输入运算符
	friend ostream& operator<<(ostream&,  BigNum&);   //重载输出运算符

	BigNum operator+(const BigNum &) const;   //重载加法运算符,两个大数之间的相加运算
	BigNum operator-(const BigNum &) const;   //重载减法运算符,两个大数之间的相减运算
	BigNum operator*(const BigNum &) const;   //重载乘法运算符,两个大数之间的相乘运算
	BigNum operator/(const int   &) const;    //重载除法运算符,大数对一个整数进行相除运算

	BigNum operator^(const int  &) const;    //大数的n次方运算
	int    operator%(const int  &) const;    //大数对一个int类型的变量进行取模运算
	bool   operator>(const BigNum & T)const;   //大数和另一个大数的大小比较
	bool   operator>(const int & t)const;      //大数和一个int类型的变量的大小比较

	void print();       //输出大数
};
BigNum::BigNum(const int b)     //将一个int类型的变量转化为大数
{
	int c,d = b;
	len = 0;
	memset(a,0,sizeof(a));
	while(d > MAXN)
	{
		c = d - (d / (MAXN + 1)) * (MAXN + 1);
		d = d / (MAXN + 1);
		a[len++] = c;
	}
	a[len++] = d;
}
BigNum::BigNum(const char*s)     //将一个字符串类型的变量转化为大数
{
	int t,k,index,l,i;
	memset(a,0,sizeof(a));
	l=strlen(s);
	len=l/DLEN;
	if(l%DLEN)
		len++;
	index=0;
	for(i=l-1;i>=0;i-=DLEN)
	{
		t=0;
		k=i-DLEN+1;
		if(k<0)
			k=0;
		for(int j=k;j<=i;j++)
			t=t*10+s[j]-'0';
		a[index++]=t;
	}
}
BigNum::BigNum(const BigNum & T) : len(T.len)  //拷贝构造函数
{
	int i;
	memset(a,0,sizeof(a));
	for(i = 0 ; i < len ; i++)
		a[i] = T.a[i];
}
BigNum & BigNum::operator=(const BigNum & n)   //重载赋值运算符,大数之间进行赋值运算
{
	int i;
	len = n.len;
	memset(a,0,sizeof(a));
	for(i = 0 ; i < len ; i++)
		a[i] = n.a[i];
	return *this;
}
istream& operator>>(istream & in,  BigNum & b)   //重载输入运算符
{
	char ch[MAXSIZE*4];
	int i = -1;
	in>>ch;
	int l=strlen(ch);
	int count=0,sum=0;
	for(i=l-1;i>=0;)
	{
		sum = 0;
		int t=1;
		for(int j=0;j<4&&i>=0;j++,i--,t*=10)
		{
			sum+=(ch[i]-'0')*t;
		}
		b.a[count]=sum;
		count++;
	}
	b.len =count++;
	return in;

}
ostream& operator<<(ostream& out,  BigNum& b)   //重载输出运算符
{
	int i;
	cout << b.a[b.len - 1];
	for(i = b.len - 2 ; i >= 0 ; i--)
	{
		cout.width(DLEN);
		cout.fill('0');
		cout << b.a[i];
	}
	return out;
}

BigNum BigNum::operator+(const BigNum & T) const   //两个大数之间的相加运算
{
	BigNum t(*this);
	int i,big;      //位数
	big = T.len > len ? T.len : len;
	for(i = 0 ; i < big ; i++)
	{
		t.a[i] +=T.a[i];
		if(t.a[i] > MAXN)
		{
			t.a[i + 1]++;
			t.a[i] -=MAXN+1;
		}
	}
	if(t.a[big] != 0)
		t.len = big + 1;
	else
		t.len = big;
	return t;
}
BigNum BigNum::operator-(const BigNum & T) const   //两个大数之间的相减运算
{
	int i,j,big;
	bool flag;
	BigNum t1,t2;
	if(*this>T)
	{
		t1=*this;
		t2=T;
		flag=0;
	}
	else
	{
		t1=T;
		t2=*this;
		flag=1;
	}
	big=t1.len;
	for(i = 0 ; i < big ; i++)
	{
		if(t1.a[i] < t2.a[i])
		{
			j = i + 1;
			while(t1.a[j] == 0)
				j++;
			t1.a[j--]--;
			while(j > i)
				t1.a[j--] += MAXN;
			t1.a[i] += MAXN + 1 - t2.a[i];
		}
		else
			t1.a[i] -= t2.a[i];
	}
	t1.len = big;
	while(t1.a[t1.len - 1] == 0 && t1.len > 1)
	{
		t1.len--;
		big--;
	}
	if(flag)
		t1.a[big-1]=0-t1.a[big-1];
	return t1;
}

BigNum BigNum::operator*(const BigNum & T) const   //两个大数之间的相乘运算
{
	BigNum ret;
	int i,j,up;
	int temp,temp1;
	for(i = 0 ; i < len ; i++)
	{
		up = 0;
		for(j = 0 ; j < T.len ; j++)
		{
			temp = a[i] * T.a[j] + ret.a[i + j] + up;
			if(temp > MAXN)
			{
				temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
				up = temp / (MAXN + 1);
				ret.a[i + j] = temp1;
			}
			else
			{
				up = 0;
				ret.a[i + j] = temp;
			}
		}
		if(up != 0)
			ret.a[i + j] = up;
	}
	ret.len = i + j;
	while(ret.a[ret.len - 1] == 0 && ret.len > 1)
		ret.len--;
	return ret;
}
BigNum BigNum::operator/(const int & b) const   //大数对一个整数进行相除运算
{
	BigNum ret;
	int i,down = 0;
	for(i = len - 1 ; i >= 0 ; i--)
	{
		ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
		down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
	}
	ret.len = len;
	while(ret.a[ret.len - 1] == 0 && ret.len > 1)
		ret.len--;
	return ret;
}
int BigNum::operator %(const int & b) const    //大数对一个int类型的变量进行取模运算
{
	int i,d=0;
	for (i = len-1; i>=0; i--)
	{
		d = ((d * (MAXN+1))% b + a[i])% b;
	}
	return d;
}
BigNum BigNum::operator^(const int & n) const    //大数的n次方运算
{
	BigNum t,ret(1);
	int i;
	if(n<0)
		exit(-1);
	if(n==0)
		return 1;
	if(n==1)
		return *this;
	int m=n;
	while(m>1)
	{
		t=*this;
		for( i=1;i<<1<=m;i<<=1)
		{
			t=t*t;
		}
		m-=i;
		ret=ret*t;
		if(m==1)
			ret=ret*(*this);
	}
	return ret;
}
bool BigNum::operator>(const BigNum & T) const   //大数和另一个大数的大小比较
{
	int ln;
	if(len > T.len)
		return true;
	else if(len == T.len)
	{
		ln = len - 1;
		while(a[ln] == T.a[ln] && ln >= 0)
			ln--;
		if(ln >= 0 && a[ln] > T.a[ln])
			return true;
		else
			return false;
	}
	else
		return false;
}
bool BigNum::operator >(const int & t) const    //大数和一个int类型的变量的大小比较
{
	BigNum b(t);
	return *this>b;
}

void BigNum::print()    //输出大数
{
	int i;
	cout << a[len - 1];
	for(i = len - 2 ; i >= 0 ; i--)
	{
		cout.width(DLEN);
		cout.fill('0');
		cout << a[i];
	}
	cout << endl;
}
char s[arrLen],s1[arrLen];
int main(void)
{
	int i,n;
     //定义大数的对象数组
    while(scanf("%s%s",s,s1)!=EOF){
        BigNum a(s),b(s1);
        a=a*b;
        a.print();
    };


}

大数加法1

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
void add(char a[],char b[],char back[])
{
    int i,j,k,up,x,y,z,l;
    char *c;
    if(strlen(a) > strlen(b))
        l = strlen(a)+2;
    else
        l = strlen(b)+2;
    c = (char*)malloc(l*sizeof(char));
    i = strlen(a)-1;
    j = strlen(b)-1;
    k = 0;
    up = 0;
    while(j>=0 || i>=0)
    {
        if(i<0) x = '0';
        else
            x = a[i];
        if(j<0) y = '0';
        else
            y = b[j];
        z = x-'0'+y-'0';
        if(up)
            z++;
        if(z>9)
        {
            up = 1;
            z%=10;
        }
        else
            up = 0;
        c[k++] = z+'0';
        i--;
        j--;
    }
    if(up)
        c[k++] = '1';
    i = 0;
    c[k] = '\0';
    for(k-=1; k>=0; k--)
        back[i++] = c[k];
    back[i] = '\0';
}
 
int main()
{
    char c[10000],t[10000],sum[1000];
    int m;
    scanf("%d%*c",&m);
    while(m--)
    {
        scanf("%s%s",c,t);
        add(c,t,sum);
        printf("%s\n",sum);
        if(m)
            printf("\n");
    }
    return 0;
}

 大数加法2

void Add(char *str1, char *str2, char *str3)
{ // str3 = str1 + str2;
	int i, j, i1, i2, tmp, carry;
	int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
	char ch;
	i1 = len1 - 1;
	i2 = len2 - 1;
	j = carry = 0;
	for (; i1 >= 0 && i2 >= 0; ++j, --i1, --i2)
	{
		tmp = str1[i1] - '0' + str2[i2] - '0' + carry;
		carry = tmp / 10;
		str3[j] = tmp % 10 + '0';
	}
	while (i1 >= 0)
	{
		tmp = str1[i1--] - '0' + carry;
		carry = tmp / 10;
		str3[j++] = tmp % 10 + '0';
	}
	while (i2 >= 0)
	{
		tmp = str2[i2--] - '0' + carry;
		carry = tmp / 10;
		str3[j++] = tmp % 10 + '0';
	}
	if (carry)
	{
		str3[j++] = carry + '0';
	}
	str3[j] = '\0';
	for (i = 0, --j; i < j; ++i, --j)
	{
		ch = str3[i];
		str3[i] = str3[j];
		str3[j] = ch;
	}
	return;
}

大数减法 

 

void Minus(char *str1, char *str2, char *str3)
{ // str3 = str1-str2 (str1 > str2)
	int i, j, i1, i2, tmp, carry;
	int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
	char ch;
	i1 = len1 - 1;
	i2 = len2 - 1;
	j = carry = 0;
	while (i2 >= 0)
	{
		tmp = str1[i1] - str2[i2] - carry;
		if (tmp < 0)
		{
			str3[j] = tmp + 10 + '0';
			carry = 1;
		}
		else
		{
			str3[j] = tmp + '0';
			carry = 0;
		}
		i1--;
		i2--;
		j++;
	}
	while (i1 >= 0)
	{
		tmp = str1[i1] - '0' - carry;
		if (tmp < 0)
		{
			str3[j] = tmp + 10 + '0';
			carry = 1;
		}
		else
		{
			str3[j] = tmp + '0';
			carry = 0;
		}
		--i1;
		++j;
	}
	--j;
	while (str3[j] == '0' && j > 0)
	{
		--j;
	}
	str3[++j] = '\0';
	for (i = 0, --j; i < j; ++i, --j)
	{
		ch = str3[i];
		str3[i] = str3[j];
		str3[j] = ch;
	}
	return;
}

大数乘以小数

#include <stdio.h>
#include <string.h>
 
void mult(char c[],int m,char t[])
{
    char s[100];
    int len=strlen(c);
    for(int i=0; i<len; i++)
        s[len-i-1]=c[i]-'0';
    int flag,add=0;
    for(int i=0; i<len; i++)
    {
        int k=s[i]*m+add;
        if(k>=10)
        {
            s[i]=k%10;
            add=k/10;
            flag=1;
        }
        else
        {
            s[i]=k;
            add=0;
            flag=0;
        }
    }
    while(add)
    {
        s[len++]=add%10;
        add/=10;
    }
    for(int i=0; i<len; i++)
        t[len-1-i]=s[i]+'0';
    t[len]='\0';
}
//大数加小数
void addt(char a[],int b,char c[])
{
    int len=strlen(a);
    char s[100];
    for(int i=0; i<len; i++)
        s[len-i-1]=a[i]-'0';
    int add=0;
    for(int i=0;; i++)
    {
        if(i>=len)
        {
            s[i]=0;
            len++;
        }
        int k=s[i]+b%10+add;
        b/=10;
        if(k>=10)
        {
            s[i]=k%10;
            add=k/10;
        }
        else
        {
            s[i]=k;
            add=0;
        }
        if(b==0&&add==0)break;
    }
    for(int i=0; i<len; i++)
        c[len-1-i]=s[i]+'0';
    c[len]='\0';
 
}
 
int main()
{
    char c[1000],t[1000],sum[1000];
    int m;
    while(~scanf("%s%d",c,&m))
    {
        mult(c,m,t);
        printf("%s\n",t);
        addt(c,m,sum);
        printf("%s\n",sum);
    }
    return 0;
}

大数乘法

void Mul(char *str1, char *str2, char *str3)
{
	int i, j = 0, i1, i2, tmp, carry, jj;
	int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
	char ch;
	jj = carry = 0;
	for (i1 = len1 - 1; i1 >= 0; --i1)
	{
		j = jj;
		for (i2 = len2 - 1; i2 >= 0; --i2, ++j)
		{
			tmp = (str3[j] - '0') + (str1[i1] - '0') * (str2[i2] - '0') + carry;
			if (tmp > 9)
			{
				carry = tmp / 10;
				str3[j] = tmp % 10 + '0';
			}
			else
			{
				str3[j] = tmp + '0';
				carry = 0;
			}
		}
		if (carry)
		{
			str3[j] = carry + '0';
			carry = 0;
			j++;
		}
		jj++;
	}
	j--;
	while (str3[j] == '0' && j > 0)
	{
		j--;
	}str3[++j] = '\0';
	for (i = 0, --j; i < j; ++i, --j)
	{
		ch = str3[i];
		str3[i] = str3[j];
		str3[j] = ch;
	}
	return;
}

大数除法

void Div(char *str1, char *str2, char *str3)
{
	int i1, i2, i, j, jj = 0, tag, carry, cf, c[MAXSIZE];
	int len1 = (int)strlen(str1), len2 = (int)strlen(str2), lend;
	char d[MAXSIZE];
	memset(c, 0, sizeof(c));
	memcpy(d, str1, len2);
	lend = len2;
	j = 0;
	for (i1 = len2 - 1; i1 < len1; ++i1)
	{
		if (lend < len2)
		{
			d[lend] = str1[i1 + 1];
			c[j] = 0;
			++j;
			++lend;
		}
		else if (lend == len2)
		{
			jj = 1;
			for (i = 0; i < lend; ++i)
			{
				if (d[i] > str2[i])
				{
					break;
				}
				else if (d[i] < str2[i])
				{
					jj = 0;
					break;
				}
			}
			if (jj == 0)
			{
				d[lend] = str1[i1 + 1];
				c[j] = 0;
				++j;
				++lend;
				continue;
			}
		}
		if (jj == 1 || lend > len2)
		{
			cf = jj = 0;
			while (d[jj] <= '0' && jj < lend)
			{
				++jj;
			}
			if (lend - jj > len2)
			{
				cf = 1;
			}
			else if (lend - jj < len2)
			{
				cf = 0;
			}
			else
			{
				i2 = 0;
				cf = 1;
				for (i = jj; i < lend; ++i)
				{
					if (d[i] < str2[i2])
					{
						cf = 0;
						break;
					}
					else if (d[i] > str2[i2])
					{
						break;
					}
					++i2;
				}
			}
			while (cf)
			{
				i2 = len2 - 1;
				cf = 0;
				for (i = lend - 1; i >= lend - len2; --i)
				{
					d[i] = d[i] - str2[i2] + '0';
					if (d[i] < '0')
					{
						d[i] = d[i] + 10;
						carry = 1;
						--d[i - 1];
					}
					else
					{
						carry = 0;
					}
					--i2;
				}
				++c[j];
				jj = 0;
				while (d[jj] <= '0' && jj < lend)
				{
					++jj;
				}
				if (lend - jj > len2)
				{
					cf = 1;
				}
				else if (lend - jj < len2)
				{
					cf = 0;
				}
				else
				{
					i2 = 0;
					cf = 1;
					for (i = jj; i < lend; ++i)
					{
						if (d[i] < str2[i2])
						{
							cf = 0;
							break;
						}
						else if (d[i] > str2[i2])
						{
							break;
						}
						++i2;
					}
				}
			}
			jj = 0;
			while (d[jj] <= '0' && jj < lend)
			{
				++jj;
			}
			for (i = 0; i < lend - jj; ++i)
			{
				d[i] = d[i + jj];
			}
			d[i] = str1[i1 + 1];
			lend = i + 1;
			j++;
		}
	}
	i = tag = 0;
	while (c[i] == 0)
	{
		++i;
	}
	for (; i < j; ++i, ++tag)
	{
		str3[tag] = c[i] + '0';
	}
	str3[tag] = '\0';
	return;
}

大数阶乘

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
    void factorial(int n,int *) ;
    int b[10000];
    int n;
    while(cin>>n)
    {
        factorial(n,b);
    }
    return 0;
}
void factorial(int n,int b[10000])
{
    long a[10000];
    int i,j,l,c,m=0,w;
    a[0]=1;
    for(i=1; i<=n; i++)
    {
        c=0;
        for(j=0; j<=m; j++)
        {
            a[j]=a[j]*i+c;
            c=a[j]/10000;
            a[j]=a[j]%10000;
        }
        if(c>0)
        {
            m++;
            a[m]=c;
        }
    }
    w = m*4+log10(a[m])+1;
    cout << w << endl;
    cout<<a[m];
    for(i=m-1; i>=0; i--)
        cout<<a[i];
    cout<<endl;
}

 

进制转换

#include <stdio.h>
#include <string.h>
 
void consversion(char s[],char s2[],long d1,long d2)
{
    long i,j,t,num;
    char c;
    num = 0;
    for(i = 0;s[i]!='\0';i++)
    {
        if(s[i]<='9' && s[i]>='0')
        t = s[i] - '0';
        else
        t = s[i] - 'A' +10;
        num = num*d1+t;
    }
    i = 0;
    while(1)
    {
        t = num%d2;
        if(t<=9)
        s2[i] = t+'0';
        else
        s2[i] = t+'A'-10;
        num/=d2;
        if(num == 0)
        break;
        i++;
    }
    for(j = 0;j<i/2;j++)
    {
        c = s2[j];
        s2[j] = s[i-j];
        s2[i-j] = c;
    }
    s2[i+1]='\0';
}
 
int main()
{
    char s1[1000],s2[1000];
    int d1,d2;
    while(~scanf("%s%d%d",s1,&d1,&d2))
    {
        consversion(s1,s2,d1,d2);
        printf("%s\n",s2);
    }
 
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值