高精度算法

高精度算法

高精度加法

问:为什么会高精度加法?

:因为数学类型的表示范围有限,以 int 为占用 4 字节,32 位,数据范围为( -232~232-1)。大概能表示 109的数据,要是超过此范围,将无法表示。

原理

就是将数一位一位的拆分,进行相加,逢十进一。
在这里插入图片描述
例题

AcWing 791.高精度加法

步骤

  1. 创建两个字符串;
  2. 创建三个整形数组;
  3. 分别将两个字符串倒序存入连个整形数组中;
  4. 将两个整形数组相加到第三个整形数组;
  5. 循环遍历第三个整形数组将大于9的元素进行除法和取;
  6. 倒序输出。

1 & 2

string s1,s2;
int x[N],y[N],z[N]={0};

3 & 4 & 5
在这里插入图片描述
在这里插入图片描述

// 将字符串中元素逆序存进数组中
for(int i=0;i<s1.size();i++)
x[s1.size()-i-1]=s1[i]-'0';
for(int i=0;i<s2.size();i++)
y[s2.size()-i-1]=s2[i]-'0';

// 判断两个字符串长度,把长度最长的给 len
int len=s1.size()>s2.size()?s1.size():s2.size();
// 数组相加
for(int i=0;i<len;i++)
z[i]=x[i]+y[i];

// 循环遍历大于9(或者大于等于10)的元素,进行除法和取模
for(int i=0;i<len;i++)
{
	if(z[i]>9)
	{
		z[i+1]+=z[i]/10;
		z[i]%=10;
	}
}

6

// 判断z[len]是否为0,增加位数
if(z[len]!=0)
len++;
for(int i=len-1;i>=0;i--)
cout<<z[i];

完整代码

#include<iostream>
using namespace std;
const int N=1e5+10;
string s1,s2;
int x[N]={0},y[N]={0},z[N]={0};
int  main()
{
	getline(cin,s1);
	getline(cin,s2);
	for(int i=0;i<s1.size();i++)
	x[s1.size()-i-1]=s1[i]-'0';
	for(int i=0;i<s2.size();i++)
	y[s2.size()-i-1]=s2[i]-'0';
	int len=s1.size()>s1.size()?s1.size():s2.size();
	for(int i=0;i<len;i++)
		z[i]=x[i]+y[i];	
	for(int i=0;i<len;i++)
	{
		if(z[i]>9)
		{	
			z[i+1]+=z[i]/10;
			z[i]%=10;	
		}
	}
	if(z[len]!=0)
	len++;	
	for(int i=len-1;i>=0;i--)
	cout<<z[i];
	return 0;
}

高精度减法

高精度减法和高精度加法基本类似。
在这里插入图片描述
例题

AcWing 792.高精度减法

步骤

定义变量

const int N=1e5+10;  //可根据实际情况进行增加或减少
int a[N]={0},b[N]={0},c[N]={0};
string s1,s2;
char flag='+';     //用于判断正负数

判断字符串长度和字典序

//如果s1的长度小于或等于s2,且s1的字典序小于s2,就需要进行交换,并改变flag
if(s1.size()<s2.size()||s1.size()==s2.size()&&s1<s2)
{
flag='-';
swap(s1,s2)
}

相减

// 如果a[i]小于b[i],就需要向前借一位。
for(int i=0;i<s1.size()-1;i++)
{
	if(a[i]<b[i])   
	{
		a[i]+=10;
		a[i+1]--;
	}
	c[i]=a[i]-b[i];
}

输出

// 需要判断从第几位开始逆序输出
int index=0;
for(int i=s1.size()-1;i>=0;i--)
{
	if(c[i]!='0')
	{
		index=i;
		break;
	}
}
// 判断正负数
if(flag=='-')
cout<<'-';

完整代码

#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N]={0},b[N]={0},c[N]={0};
string s1,s2;
int main()
{
	char flag='+';
	getline(cin,s1);
	getline(cin,s2);
	if(s1.size()<s2.size()||s1.size()==s2.size()&&s1<s2)
	{
	swap(s1,s2);
	flag='-';
	}
	for(int i=0;i<s1.size();i++) a[s1.size()-1-i]=s1[i]-'0';
	for(int i=0;i<s2.size();i++) b[s2.size()-1-i]=s2[i]-'0';
	for(int i=0;i<s1.size();i++)
	{
		if(a[i]<b[i])
		{
			a[i]+=10;
			a[i+1]--;
		}
		c[i]=a[i]-b[i];
	}
	int index=0;
	for(int i=s1.size()-1;i>=0;i--)
	{
		if(c[i]!=0)
		{
			index=i;
			break;
		}
	}
	if(flag=='-')
	cout<<'-';
	for(int i=index;i>=0;i--)
	cout<<c[i];
	return 0;
}

高精度乘法

在这里插入图片描述
!!!这里的 t 是进位的意思,另外还需要判断一下如果n为0直接结束程序输出入0
例题

AcWing 793.高精度乘法

步骤

定义变量

const int N=1e5+10; //可根据题目条件自行增加
int a[N],b[N],n;
string s1;
int t=0,len=0;  //t是进位,len用于记录长度

n 为 0

if(!n) 
cout<<0;

n 不为 0

//将字符串内容倒序存入数组a中
for(int i=0;i<s1.size();i++)
a[s1.size()-i-1]=s1[i]-'0';
//s1的每一位与n相乘
for(int i=0;i<s1.size()||t;i++)
{
	if(i<s1.size()) t+=a[i]*n;
	b[i]=t%10;
	len++;    //用于记录位数
	t/=10;
}

完整代码

#include<iostream>
using namespace std;
string s1;
int n;
const  int N=1e5+10;
int a[N],b[N]; 
int  main()
{
	int t=0,len=0;
	getline(cin,s1);
	cin>>n;
	if(!n) cout<<0;
	else
	{
		for(int i=0;i<s1.size();i++) 
		a[s1.size()-i-1]=s1[i]-'0';
		for(int i=0;i<s1.size()||t;i++)
		{
			if(i<s1.size()) t+=a[i]*n;
			b[i]=t%10;
			len++;
			t/=10;
		}
		for(int i=len-1;i>=0;i--)
			cout<<b[i];	
	}
	return 0;
}

高精度除法

在这里插入图片描述
这里 r 是指余数,n 为除数,高精度除法与前面—高精度(加/减/乘法)不同在于不用讲字符串倒序存入整型数组中。

例题
794. 高精度除法

步骤

定义变量

const int N=1e5+10; //可根据题自行增加减少
int a[N],b[N],n; //n为除数
string s;
int len=0,cnt=0,r=0; //r是余数,cnt记录0的个数,len记录位数

实现

for(int i=0;i<s.size();i++)
{
	r=r*10+a[i];
	b[i]=r/n;
	r%=n;
	len++;
	if(!b[i]) cnt++;
}

输出

if(cnt==len) cout<<0;  //如果(cnt记录0的个数)cnt的位数与 len 相等则直接输入一个0即可
else
{
	//用于判断从第几位输出
	int index=0;
	for(int i=0;i<len;i++)
	{
		if(b[i]!=0) 
		{
			index=i;
			break;
		}
	}
	
	for(int i=index;i<len;i++) cout<<b[i];
}
//最后输出余数即可
0cout<<endl<<r<<endl;

完整代码

#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N],n,b[N];
string s;
int  main()
{
	getline(cin,s);
	cin>>n;
	for(int i=0;i<s.size();i++)	a[i]=s[i]-'0';
	int r=0,cnt=0,len=0;
	for(int i=0;i<s.size();i++)
	{
		r=r*10+a[i];
		b[i]=r/n;
		r%=n;
		len++;
		if(!b[i]) cnt++;
	}
	if(cnt==len) cout<<0;
	else
	{
		int index=0;
		for(int i=0;i<len;i++)	if(b[i]!=0) {index=i;break;}
		for(int i=index;i<len;i++) cout<<b[i];
	}
	cout<<endl<<r<<endl;
	return 0;
}
  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值