第一章 高精度(一)

自我介绍:大家好,我是小鱼,目前是一名本科大二的学生,这是我的第一篇,在接下来的日子里,我将会分类讲解各种不同的数据结构与算法,希望可以与大家共同进步,共同成长。

本章介绍:众所周知,在处理数与数的运算时,一旦两个数的位数超过了所使用文章的数据类型时,便会出现溢出(对于数的溢出,我们在后续的文章中会详细讲解)。为了应对这种情况,高精度算法应运而生。高精度算法是用于计算机对于超大数据的一种模拟加、减、乘、除、乘方、阶乘等运算。(本章的代码已通过洛谷和ACWing的全部测试点)

4种数据类型及取值范围:

byte:-2^7~2^7-1   ,即  -128~127,  1字节

short:-2^15~2^15-1   ,即-32768~32767 ,   2字节

有符号 int  : -2^31~2^31-1   ,即-2147483648~2147483647,   4字节

无符号 int  : 0~2^32-1

long : -2^63~2^63-1   ,即-9223372036854774808~9223372036854774807,   8字节

高精度加法

题目描述:

给定两个正整数a,b,计算它们的和。

输入格式:

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

输出格式:

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

数据范围:

a,b10500

题目分析:

本题目是最基础的高精度题型,对于这类问题,我通常采用字符串处理。

核心点:与小学时做加法的步骤相似,一位一位的对着加,注意存储进位。

本题另一个核心点就是明白数字和字符串的区别在哪里,即个位数字在哪里

1.使用数字存储时,个位是字符串的最后一位;

2.两个字符串相加,因为字符串的长度可能不一致,所以最好翻转过来,这样字符串就变成了个位在前;

3.相加的过程即,定义一个s=0,用s分别与每个字符串的第i,j位相加,十位做下一次循环;

复制代码
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4 using namespace std;
 5 const int N=100010;
 6 string A,B;
 7 string add(const string &A,const string &B){
 8     string C;//C=A+B;
 9     int s=0;
10     for(int i=A.size()-1,j=B.size()-1;i>=0||j>=0||s>0;i--,j--){
11         if(i>=0) s+=(A[i]-'0');
12         if(j>=0) s+=(B[j]-'0');
13         C+=((s%10)+'0');//用C来存储相加的结果
14         s=s/10;//去除掉s的个位,把s的十位放到下一次的循环中
15     }
16     reverse(C.begin(),C.end());
17     return C;
18 }
19 int main(){
20     cin>>A>>B;
21     cout<<add(A,B)<<endl;
22     return 0;
23 }
复制代码

附上高精度加法的代码模板

复制代码
 1 string add(const string &A,const string &B){
 2     string C;//C=A+B;
 3     int s=0;
 4     for(int i=A.size()-1,j=B.size()-1;i>=0||j>=0||s>0;i--,j--){
 5         if(i>=0) s+=(A[i]-'0');
 6         if(j>=0) s+=(B[j]-'0');
 7         C+=((s%10)+'0');
 8         s=s/10;
 9     }
10     reverse(C.begin(),C.end());
11     return C;
12 }
复制代码

高精度减法

题目描述:

给定两个正整数a,b,计算它们的差。

输入格式:

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

输出格式:

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

数据范围:

a,b10500

题目分析:

高精度减法的思想与高精度加法类似,可以用同一种思路写。但对减完之后0的后缀问题和字典序大小的比较仍需要讨论

核心思想:

1.同上面高精度加法,但对于类似30-30的问题,计算结果可能会出现00的情况,或输入003、10得到结果应为-8.面对这种情况,我们应该才用去0操作,分别在处理数据前,做去0操作,在计算后,对计算结果,做去0操作;

2.减法需要比较字典序的大小,字典序较大的应作为被减的一方,以防止出现倒序后高位不够减的情况;

复制代码
 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 const int N = 1000010;
 5 
 6 bool cmp(vector<int> &A, vector<int> &B)//比较A,B的字典序,用字典序大的减小的 
 7 {
 8     if (A.size() != B.size()) return A.size() >= B.size();
 9     for (int i = A.size() - 1; i >= 0; i--) 
10         if (A[i] != B[i])
11             return A[i] > B[i];
12     return true;
13 }
14 
15 void trimZero(vector<int> &A)//去0操作 
16 {
17     while (A.back() == 0 && A.size() > 1) A.pop_back();//若A的最后一位是0且A至少有一位,去除A的0后缀 
18 }
19 
20 vector<int> sub(vector<int> &A, vector<int> &B)
21 {
22     vector<int> C;
23     int t = 0;
24     for (int i = 0; i < A.size(); i++)
25     {
26         t = A[i] - t;
27         if (i < B.size()) t -= B[i];
28         C.push_back((t + 10) % 10);
29         if (t < 0) t = 1;//t<0说明t向前借了一位 
30         else t = 0;//否则把t置为0,进行下一位的运算 
31     }
32     trimZero(C);
33     return C;
34 }
35 
36 int main()
37 {
38     string a, b;
39     cin >> a >> b;
40     vector<int> A, B, C;
41     for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');//把字符串转为数字 
42     for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
43 
44     trimZero(A), trimZero(B);//去后缀0 
45 
46     if (cmp(A, B)) C = sub(A, B);
47     else {
48         C = sub(B, A);
49         printf("-");
50     }
51     for (int i = C.size() - 1; i >= 0; i--) cout << C[i];
52     return 0;
53 }
复制代码

附上高精度减法的代码模板

复制代码
 1 bool cmp(vector<int> &A, vector<int> &B)//比较A,B的字典序,用字典序大的减小的 
 2 {
 3     if (A.size() != B.size()) return A.size() >= B.size();
 4     for (int i = A.size() - 1; i >= 0; i--) 
 5         if (A[i] != B[i])
 6             return A[i] > B[i];
 7     return true;
 8 }
 9 
10 void trimZero(vector<int> &A)//去0操作 
11 {
12     while (A.back() == 0 && A.size() > 1) A.pop_back();//若A的最后一位是0且A至少有一位,去除A的0后缀 
13 }
14 
15 vector<int> sub(vector<int> &A, vector<int> &B)//做A-B操作 
16 {
17     vector<int> C;
18     int t = 0;
19     for (int i = 0; i < A.size(); i++)
20     {
21         t = A[i] - t;
22         if (i < B.size()) t -= B[i];
23         C.push_back((t + 10) % 10);
24         if (t < 0) t = 1;//t<0说明t向前借了一位 
25         else t = 0;//否则把t置为0,进行下一位的运算 
26     }
27     trimZero(C);
28     return C;
29 }
复制代码

 

总结

这篇文章讲解了高精度加法和高精度减法的求解方法关键点如下:

高精度加法

1.记住字符串中个位在后面,高位在前面,要把字符串翻转一下;

2.定义一个s=0,用s分别与每个字符串的第i,j位相加,十位做下一次循环;

高精度加法

1.后缀为0的情况要去0;

2.比较字典序的大小,字典序大的作为减数;

 

接下来的文章将为大家介绍高精度乘法和高精度除法,难度会有所提升,大家敬请期待。

 

posted @ 2021-11-18 18:51  Apricity001  阅读(13)  评论(0)    收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示