高精度算法的实现

因为日常中没有把一些算法模板存储下来的习惯,而高精度算法又是如此地麻gui烦chu,于是便产生了放在blog里的想法。


高精度加法

#include<iostream>
using namespace std;
// 采用数组倒序存储数字方便进位计算
int a[100],b[100],c[100];
void add()
{
	int x=0,i=1;
	// 加法运算
	for(;i<=a[0]||i<=b[0];i++)
	{
		// c数组为结果数组 它等于a[i]+b[i]+x x为当前累计的进位
		c[i]=a[i]+b[i]+x;
		// 计算进位
		x=c[i]/10;
		c[i]%=10;
	}
	// 若有剩下的进位,则累加进去
	c[i]=x;
}
main()
{
	string a1,a2;
	cin>>a1>>a2;
	// 倒序存储数字 a[0]记录数字长度
	for(int i=a1.size()-1,j=1;i>=0;i--,j++)
	{
		a[j]=a1[i]-'0';
		a[0]++;
	}
	for(int i=a2.size()-1,j=1;i>=0;i--,j++)
	{
		b[j]=a2[i]-'0';
		b[0]++;
	}
	add();
	// 设置一个flag标记是否遍历完前导0
	bool flag=0;
	// 倒序输出
	for(int i=99;i>=1;i--)
	{
		if(!c[i]&&!flag)continue;
		flag=1;
		cout<<c[i];
	}
}

# 高精度减法
#include<iostream>
using namespace std;
int a[100],b[100],c[100];
void subtract()
{
	for(int i=1;i<=a[0]||i<=b[0];i++)
	{
		// 若不够减,则借一位说话
		if(a[i]<b[i])a[i]+=10,a[i+1]--;
		c[i]=a[i]-b[i];
	}
}
main()
{
	// 字符输入&存储 与高精加法类似 
	string a1,a2;
	cin>>a1>>a2;
	// 需要注意,若a1比a2来得短,或a1比a2小,则输出负号-
	if(a1.size()<a2.size()||(a1.size()==a2.size()&&a1<a2))swap(a1,a2),cout<<'-';
	// 这里写的时候没注意,输出总是少一位 i应该设置为≥0 否则数字的最高位不会读入
	for(int i=a1.size()-1,j=1;i>=0;i--,j++)
	{
		a[j]=a1[i]-'0';
		a[0]++;
	}
	for(int i=a2.size()-1,j=1;i>=0;i--,j++)
	{
		b[j]=a2[i]-'0';
		b[0]++;
	}
	subtract();
	// 同上,标记前导0
	bool flag=0;
	for(int i=100-1;i>=1;i--)
	{
		if(!c[i]&&!flag)continue;
		flag=1;
		cout<<c[i];
	}
}

# 高精度乘法
#include<iostream>
using namespace std;
int a[100],b[100],c[100];
void multiply()
{
	int i=1,j;
	for(;i<=a[0];i++)
	{
		// x为进位
		int x=0;
		// 对于b中的每一位
		for(j=1;j<=b[0];j++)
		{
			// 将c的第i+j-1位累加入乘积以及当前进位
			c[i+j-1]+=a[i]*b[j]+x;
			// 计算进位
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
		// 将剩余的进位计入下一位
		c[i+j-1]=x;
	}
}
main()
{
	// 完全一样的数据读入
	string a1,a2;
	cin>>a1>>a2;
	for(int i=a1.size()-1,j=1;i>=0;i--,j++)
	{
		a[j]=a1[i]-'0';
		a[0]++;
	}
	for(int i=a2.size()-1,j=1;i>=0;i--,j++)
	{
		b[j]=a2[i]-'0';
		b[0]++;
	}
	multiply();
	bool flag=0;
	for(int i=100-1;i>=1;i--)
	{
		if(!c[i]&&!flag)continue;
		flag=1;
		cout<<c[i];
	}
}

# 高精度除法(除数为非高精度数)
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int a[110],b,c[123456],mod;
void divide()
{
	// 此次除法的余数
	int x=0;
	// 对于每一位被除数,商=上一次余数*10+此位被除数 除以 除数
	for(int i=1;i<=a[0];i++)
	{
		c[i]=(x*10+a[i])/b;
		x=(x*10+a[i])%b;
	}
	// 剩下的除不尽的即为余数
	mod=x;
}
main()
{
	// 初始化为-1方便处理后缀0的情况
	memset(c,-1,sizeof(c));
	string a1,a2;
	cin>>a1>>b;
	// 对于除法,因为无需进位,故正序存储
	for(int i=1;i-1<a1.size();i++)
	{
		a[i]=a1[i-1]-'0';
		a[0]++;
	}
	divide();
	// 同样,记前导0状态
	bool flag=0;
	for(int i=1;i<123456&&c[i]!=-1;i++)
	{
		if(!c[i]&&!flag)continue;
		flag=1;
		cout<<c[i];
	}
	if(!flag)cout<<0;
}

# 高精度除法(除数为高精度数)
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int a[100],b[100],c[100];
// 因为除数也是高精度数,对于这种比较骚气的处理
// 我们采用减法模拟除法,对于每一位都逐个减去除数*位权
// 如对于666/3 我们先用666-300-300=66 商记为2 再66-30-30=6 商记为22 最后6-3-3=0 商为222
// 比较高精度数a与高精度数b
int compare(int a[],int b[])
{
	int i;
	if(a[0]>b[0])return 1;
	if(a[0]<b[0])return -1;
	for(i=a[0];i>0;i--)
	{
		if(a[i]>b[i])return 1;
		if(a[i]<b[i])return -1;
	}
	return 0;
}
// 高精度数 a-=b
void subtract(int a[],int b[])
{
	int flag=compare(a,b),i;
	if(!flag)
	{
		a[0]=0;
		return;
	}
	// 若a>b,则进行高精度减法
	if(flag==1)
	{
		for(int i=1;i<=a[0];i++)
		{
			if(a[i]<b[i])
			{
				a[i+1]--;
				a[i]+=10;
			}
			a[i]-=b[i];
		}
		// 删去前导0
		while(a[0]>0&&a[a[0]]==0)a[0]--;
		
	}
}
main()
{
	string m,n;
	int i,j;
	cin>>m>>n;
	// 因为要进行减法,故逆序存储数字
	for(i=m.size()-1,j=1;i>=0;i--,j++)a[j]=m[i]-'0',a[0]++;
	for(i=n.size()-1,j=1;i>=0;i--,j++)b[j]=n[i]-'0',b[0]++;
	int temp[100];
	// 商的位数=被除数位数-除数位数+1
	int len=a[0]-b[0]+1;
	// 从高位到低位进行运算
	for(i=len;i>0;i--)
	{
		memset(temp,0,sizeof(temp));
		// temp为b*位权
		// 为了达到此目的,我们采用错位存储的方式 对于每一位j,加上此时位数i后-1(因为j是从1开始的)
		for(j=1;j<=b[0];j++)temp[i+j-1]=b[j];
		// 记录此时temp的位数
		temp[0]=b[0]+i-1;
		// 以减法模拟除法
		while(compare(a,temp)>=0)c[i]++,subtract(a,temp);
	}
	// 前导0标记
	bool flag=0;
	// 输出商
	for(i=99;i>=1;i--)
	{
		if(!flag&&!c[i])continue;
		flag=1;
		cout<<c[i];
	}
	if(!flag)cout<<0;
	cout<<endl;
	flag=0;
	// 输出余数
	for(i=a[0];i>=1;i--)
	{
		if(!flag&&!a[i])continue;
		flag=1;
		cout<<a[i];
	}
	if(!flag)cout<<0;
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值