8.2 高精度算法

高精度算法的代码思路:模拟竖式计算

加法

洛谷P1601 A+B Problem(高精)
题目描述

高精度加法,相当于 a+b problem,不用考虑负数

输入格式

分两行输入。 a , b ≤ 1 0 500 a,b \leq 10^{500} a,b10500

输出格式
输出只有一行,代表 a + b a+b a+b 的值。

样例 #1

样例输入 #1

1
1

样例输出 #1

2

样例 #2

样例输入 #2

1001
9099

样例输出 #2

10100

代码实现

#include<iostream>
#include<vector> 
using namespace  std;

vector<int> A,B;//vec不容易越界

vector<int> add(vector<int>A,vector<int>B)//vec传参格式
{
	int t=0;//储存进位
	int lena=A.size(),lenb=B.size();//存储长度 优化
	vector<int>C;
	for(int i=0,j=0;i<lena||j<lenb||t;i++,j++)//i,J分别对应A,B指针
	//当A,B其中一个没有将所有数位加完,或进位没有进完时,还要继续加下去
	{
		if(i<lena)
		{
			t+=A[i];
		}
		if(j<lenb)
		{
			t+=B[j];
		}
		C.push_back(t%10);//模拟竖式,最大9*9=81,两位数,所以模10取个位
		t/=10;//进位
	}
	return C;
}
 
int main()
{
	string a,b;
	cin>>a>>b;
	
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
	
	vector<int>C=add(A,B);
	for(int i=C.size()-1;i>=0;i--)
	{
		cout<<C[i];
	}
	return 0;
} 

减法

洛谷P2142 高精度减法

题目描述

高精度减法。

输入格式

两个整数 a , b a,b a,b(第二个可能比第一个大)。

输出格式

结果(是负数要输出负号)。

样例 #1

样例输入 #1

2
1

样例输出 #1

1

提示

  • 20 % 20\% 20% 数据 a , b a,b a,b 在 long long 范围内;
  • 100 % 100\% 100% 数据 0 < a , b ≤ 1 0 10086 0<a,b\le 10^{10086} 0<a,b1010086

代码实现

#include<iostream>
#include<vector> 
using namespace  std;

vector<int> A,B;

int check(string a,string b)
//减法要新写函数来判断大小
{
	if(a.size()!=b.size())//如果a和b长度不一样
	{
		return a.size() > b.size();//返回长度更长的那个
	}
	for(int i=0;i<a.size();i++)//如果一样,找到不一样的那个
	{
		if(a[i]!=b[i])
		{
			return a[i]>b[i]; //返回同数位上,数更大的那个
		}
	}
	return 1;//如果a>b 返回1
}

vector<int> sub(vector<int>A,vector<int>B)
{
	int r=0;//存储借位
	int lena=A.size(),lenb=B.size();
	vector<int>C;
	for(int i=0,j=0;i<lena;i++,j++)//减法的循环次数不会超过大数位数
	{
		r=A[i]-r;//减数借位
		if(j<lenb)
		{
			r-=B[j];
		}
		C.push_back((r+10)%10);//有可能r是负数,所以+10再取模
		r=(r>=0?0:1);
		//if(r>=0) return 0 else return 1
	}
	while(C.size()>1&&C.back()==0) C.pop_back(); //去掉高位的0
	return C;
}
 
int main()
{
	string a,b;
	cin>>a>>b;
	
	if(!check(a,b)) swap(a,b),cout<<"-";
	//如果a<b ab交换位置再进行计算,且要输出负号
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
	
	vector<int>C=sub(A,B);
	for(int i=C.size()-1;i>=0;i--)
	{
		cout<<C[i];
	}
	return 0;
} 

乘法

洛谷P1303 A*B Problem

题目描述

给出两个非负整数,求它们的乘积。

输入格式

输入共两行,每行一个非负整数。

输出格式

输出一个非负整数表示乘积。

样例 #1

样例输入 #1

1 
2

样例输出 #1

2

提示

每个非负整数不超过 1 0 2000 10^{2000} 102000

代码实现

#include<bits/stdc++.h>
using namespace std;
vector<int>A,B;

vector<int> mul(vector<int>A,vector<int>B)
{
	int lena=A.size(),lenb=B.size();
	vector<int> C(lena+lenb);//C的长度是lena+lenb
	for(int i=0;i<lena;i++)//乘法模拟竖式,需要双重循环
	{
		for(int j=0;j<lenb;j++)
		{
			C[i+j]+=A[i]*B[j];//结果的第i+j位,是Ai和Bj的指针之和
			C[i+j+1]+=C[i+j]/10;//下一位+上 上一位的进位
			C[i+j]%=10;//进位后取模 保留个位
		}
	}
	while(C.size()>1&&C.back()==0) C.pop_back(); //去除高位0
	return C;
}

int main()
{
	string a,b;
	cin>>a>>b;
	
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
	
	vector<int>C=mul(A,B);
	
	
	for(int i=C.size()-1;i>=0;i--)
	{
		cout<<C[i];
	}
	 
	return 0;
}

除法


洛谷P1480 A/B Problem

题目描述

输入两个整数 a , b a,b a,b,输出它们的商。

输入格式

两行,第一行是被除数,第二行是除数。

输出格式

一行,商的整数部分。

样例 #1

样例输入 #1

10
2

样例输出 #1

5

提示

0 ≤ a ≤ 1 0 5000 0\le a\le 10^{5000} 0a105000 1 ≤ b ≤ 1 0 9 1\le b\le 10^9 1b109

代码实现

#include<bits/stdc++.h>
using namespace std;
vector<int>A;

vector<int> div(vector<int>A,int b)
{
	long long r=0;//存储余数
	//防止越界,使用long long类型
	vector<int>C;
	for(int i=A.size()-1;i>=0;i--)
	//除法是正着除,输入是倒着的,所以倒着循环
	{
		r=r*10+A[i];//上一次的余数+这一次的数=这一次的被除数
		C.push_back(r/b);
		r=r-r/b*b;//减去商*除数,就是余数
	}
	reverse(C.begin(),C.end());//倒着输出
	while(C.size()>1&&C.back()==0) C.pop_back(); //去除高位0
	return C;
}

int main()
{
	string a;
	int b;//被除数不是高精度,所以直接用int
	cin>>a>>b;
	
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	
	vector<int>C=div(A,b);
	
	
	for(int i=C.size()-1;i>=0;i--)
	{
		cout<<C[i];
	}
	 
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值