高精度的四则运算

高精度运算里的最重要的思想就是将数值以字符串(string)的形式输出。然后利用容器(vector)进行逆序读入。再然后就是前一位的进位(加、乘)或借位(减除)根据所要进行的运算来运用不同的思想。

高精度的加法:

处理好前一位的进位

加法的习惯是从个位逐步向前运算,这就是为什么要逆序输入的原因。假设高精度的运算公式我们记为:A[i]+B[i]=C[i],进位设为t。那么C[i]该数位上的值为(A[i]+B[i]+t)%10。

题目:

给定两个正整数(不含前导 00),计算它们的和。

输入格式

共两行,每行包含一个整数。

输出格式

共一行,包含所求的和。

数据范围

1≤整数长度≤1000001≤整数长度≤100000

输入样例:
12
23
输出样例:
35

代码如下:

#include<iostream>
#include<vector>//使用vector容器前需包含此文件

using namespace std;
//vector(vector &v) ; //加上'&' 为引用数组v,则不需要再拷贝一份,提高效率
vector<int> add(vector<int> &A,vector<int> &B)
{
    
    vector<int> C;
    //进位标识符t
    int t=0;
    for(int i=0;i<B.size()||i<A.size();i++)
    {
        /*
        两个if语句都是在判断A或B容器对应的数位上是否还有数据
        如果没有则对应数位上是+0,即不加。
        */
        if(i<A.size()) t+=A[i];
        if(i<B.size()) t+=B[i];
        //要的是t个位上的数
        C.push_back(t%10);
        //舍弃掉个位数,让t十位数上的值参与到下一位数的运算中
        t/=10;
    }
    //如果t不等于零,则在最高位补1。对应数位相加(两位数的加法),进位是0或1;
    if(t) C.push_back(1);
    return C;
}
int main()
{
    string a,b;
    /*
    vector<int> 把vector理解成一个数组,但与数组不同的是:
    vector是动态储存,保存在堆中。
    动态扩展是找到比原来更大的内存空间,将原数据拷贝到新空间,释放 原 空间
    */
    vector<int> A,B;
    
    cin >> a >> b;
    
    /*
    push_back()是将括号里的元素插入至尾部
    A.push_back(a[i]-'0')//意味着将a[i]-'0'这个数插到A容器的最后面
    但由于A容器中无元素,所以插到了第一位上
    */
//逆序读入,方便于运算
    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;
    
    
}

----------------------------------------------------------------------------

高精度的减法:

 

处理好前一位的借位

假设对应的高精度的减法为:A[i]-B[i]=C[i]。那么C[i] 位数上对应的数值就为(A[i]-B[i]+t+10)%10。小细节:如果本位被借位了,t=-1,否则t=0。加10再mod10容纳了借位与不借位的两种情况。

题目:

给定两个正整数(不含前导 00),计算它们的差,计算结果可能为负数。

输入格式

共两行,每行包含一个整数。

输出格式

共一行,包含所求的差。

数据范围

1≤整数长度≤1051≤整数长度≤105

输入样例:
32
11
输出样例:
21

 代码:

/*
    C.back是C++标准库中的一个容器适配器,它基于底层容器实现了栈(stack)的功能。栈是一种遵循后进先出(LIFO)原则的数据结构,只允许在栈顶进行插入和删除操作。

C.back提供了以下几个主要的成员函数:

push:将元素压入栈顶。
pop:将栈顶元素弹出。
top:返回栈顶元素的引用,但不删除该元素。
empty:判断栈是否为空。
size:返回栈中元素的个数。
    */

#include<bits/stdc++.h>
#include<vector>

using namespace std;
/*
判断a与b的大小
*/
bool check(vector<int> &a,vector<int> &b)
{
    //长度不相等,直接返回a.size()>b.size(),如果a.size()>b.size()则为真,否则为假
    if(a.size()!=b.size()) return a.size()>b.size();
    //长度不相等
    for(int i=a.size();i>=0;i--)//从最高位开始判断
    //如果最高位不相等
      if(a[i]!=b[i])
    //同上
        return a[i]>b[i];
    //两种情况都判断过还是没结果,说明a=b,直接返回真
    return true;
}
//减,对应数位相减
vector<int> sub(vector<int> &a,vector<int> &b)
{
    //经过check函数之后,a的大小一定大于b
    vector<int> C;//定义容器C
    int t=0;
    for(int i=0;i<a.size();i++)
    {
        t+=a[i];
        if(i<b.size()) t-=b[i];
        //倘若相减为负数,那么需进行借位操作。为正也不影响
        C.push_back((t+10)%10);
        //重新对t赋值
        if(t<0) t=-1;
        else t=0;
    }
    //这一步是去前导0,如果用数组来做,那就是压缩数组C的体积
    //注意即使全为0,那么就要保存最后一位
    while(C.size()>1&&C.back()==0) C.pop_back();//去顶
    return C;
}
int main()
{
    string a,b;
    cin >> a >> b;
    vector<int> A,B,C;
    
    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');

    
    if(check(A,B))
    {
        C=sub(A,B);
        for(int i=C.size()-1;i>=0;i--) cout << C[i];
        return 0;
    }
    else
    {
        C=sub(B,A);
        //如果A的长度小于B,提前输出一个符号
        cout << "-";
        for(int i=C.size()-1;i>=0;i--) cout << C[i];
        return 0;
    }
    
}

---------------------------------------------------------------------

高精度的乘法

 这里的乘法与平日里所用的的不一致因为平日里的不好处理进位。
记录一下y总的思路:先计算出a的个位与小整数b的乘积记为t
则结果个上位的数值就为t % 10
对下一位的进位为t/10。

题目

给定两个非负整数(不含前导 00) A𝐴 和 B𝐵,请你计算 A×B𝐴×𝐵 的值。

输入格式

共两行,第一行包含整数 A𝐴,第二行包含整数 B𝐵。

输出格式

共一行,包含 A×B𝐴×𝐵 的值。

数据范围

1≤A的长度≤1000001≤𝐴的长度≤100000,
0≤B≤100000≤𝐵≤10000

输入样例:
2
3
输出样例:
6

代码:

#include<bits/stdc++.h>
#include<vector>
using namespace std;
/*
当该位的值 %10之后 ,所剩下的数就是该进制下的数。若想进位到前者
则需要/10。上一位的数放到下一位的时候权重就会少10。
'0'=48,'a'=97,'A'=65 
*/
vector<int> mul(vector<int> a,int b)
{
	vector<int> c;
	int t=0;
	//y总对算法思路的掌握当真是令我五体投地!!
	/*这里||t的运用是我没能想到的,即是对最高位的
	的进位。如果不加这一步,总会缺个最高位
	*/
	for(int i=0;i<a.size()||t;i++)
	{
		if(i<a.size()) t+=a[i]*b;
		//每一位数的值。。如果最后数值已经乘完,只有进位时,按照此规律将其附在后面就行
		c.push_back(t%10);
		//进位
		t/=10;
	}
	//去前导0(更简洁的做法是特判一下b是否为0)
	while(c.size()>1&&c.back()==0) c.pop_back();
	return c;
}
int main()
{
	string a;
	int b;
	cin  >> a >> b;
//倒序输入,方便运算
	vector<int> c;
	for(int i=a.size()-1;i>=0;i--) c.push_back(a[i]-'0');

	vector<int> sum;
	sum=mul(c,b);
//倒序输出	
	for(int i=sum.size()-1;i>=0;i--) cout << sum[i];
	return 0;
	
} 

----------------------------------------------------------------

 高精度的除法:

也是对借位的处理。但是低位向高位借位时高位的权值会加10.

题目:

给定两个非负整数(不含前导 00) A,B𝐴,𝐵,请你计算 A/B𝐴/𝐵 的商和余数。

输入格式

共两行,第一行包含整数 A𝐴,第二行包含整数 B𝐵。

输出格式

共两行,第一行输出所求的商,第二行输出所求余数。

数据范围

1≤A的长度≤1000001≤𝐴的长度≤100000,
1≤B≤100001≤𝐵≤10000,
B𝐵 一定不为 00

输入样例:
7
2
输出样例:
3
1

代码:

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

vector<int> div(vector<int> &A,int &b,int &r)
{
	vector<int> C;
/*
    高精度的加、减、乘都是从原字符串的个位开始运算,而除法是从高位
	向低位进行运算。为了保持四则输入输出的完整性,
	在这里牺牲掉函数。 
*/

//从最高位开始运算,而由于输入时是逆序输入,所以运算时从
//A容器的最后面开始运算,令i=A.size()-1 
	for(int i=A.size()-1;i>=0;i--)
	{
		/*余数r,该位的被除数等于这一位的数值+
		上一位余数的十倍 (上一位是高位,降位权值扩大十倍)*/
		r=r*10+A[i];
		//结果的位数数值等于被除数/除数 
		C.push_back(r/b);
		//取余 
		r=r%b;
	}
	//如上所述,为了保持输出(逆序)的一致性,在这里将正序的C再逆序一边。 
	reverse(C.begin(),C.end());//调用该函数需要包含#include<algorithm>头文件
	//去前导0 
	while(C.size()>1&&C.back()==0) C.pop_back();
	return C;
}
int main()
{
	string A;
	int b;
	cin >> A >>b;
	vector<int> B,C;
	//逆序输入 
	for(int i=A.size()-1;i>=0;i--) B.push_back(A[i]-'0');
	
	int r=0;
	C=div(B,b,r);
	//逆序输出 
	for(int i=C.size()-1;i>=0;i--) cout << C[i];
	cout << endl << r;
	
	return 0;
}

 ——————————————————————————————————————————

附上板子:

高精度的加法:

vector<int> add(vector<int> A,vector<int> B)
{
    vector<int> C;
    
    int t=0;
    for(int i=0;i<A.size()||i<B.size();i++)
    {
        if(i<A.size()) t+=A[i];
        if(i<B.size()) t+=B[i];
        C.push_back(t%10);
        t/=10;
    }
//特判最后一次运算是否需要进一
    if(t) C.push_back(1);
    return C;
}
int main()
{
    string a,b;
    cin >> a >> b;
    vector<int> 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;
    
}

高精度的减法 :

//一般为大数减小数。如果输入时为小数减大数,提前输出一个负号就可以了
bool check(vector<int> &a,vector<int> &b)
{
    if(a.size()!=b.size()) return a.size()>b.size();
    
    for(int i=a.size();i>=0;i--)
      if(a[i]!=b[i])
        return a[i]>b[i];
    return true;
}

vector<int> sub(vector<int> &a,vector<int> &b)
{
    vector<int> C;
    int t=0;
    for(int i=0;i<a.size();i++)
    {
        t+=a[i];
        if(i<b.size()) t-=b[i];
        C.push_back((t+10)%10);
        if(t<0) t=-1;
        else t=0;
    }
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}

高精度乘法: 


vector<int> mul(vector<int> a,int b)
{
	vector<int> c;
	int t=0;
	for(int i=0;i<a.size()||t;i++)
	{
		if(i<a.size()) t+=a[i]*b;
		c.push_back(t%10);
		t/=10;
	}
	
	while(c.size()>1&&c.back()==0) c.pop_back();
	return c;
}

高精度除法: 


vector<int> div(vector<int> &A,int &b,int &r)
{
	vector<int> C;
/*
    高精度的加、减、乘都是从原字符串的个位开始运算,而除法是从高位
	向低位进行运算。为了保持四则输入输出的完整性,
	在这里牺牲掉函数。 
*/

//从最高位开始运算,而由于输入时是逆序输入,所以运算时从
//A容器的最后面开始运算,令i=A.size()-1 
	for(int i=A.size()-1;i>=0;i--)
	{
		r=r*10+A[i];
		C.push_back(r/b);
        r=r%b;
	}
	//如上所述,为了保持输出(逆序)的一致性,在这里将正序的C再逆序一边。 
	reverse(C.begin(),C.end());
	//去前导0 
	while(C.size()>1&&C.back()==0) C.pop_back();
	return C;
}

高精度 结束!!!

  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值