Skip to content

Commit f9680b1

Browse files
committed
feat: add 高精度
1 parent 434d04d commit f9680b1

File tree

4 files changed

+677
-0
lines changed

4 files changed

+677
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
### 题目描述
2+
给定两个正整数(不含前导 $0$),计算它们的和。
3+
4+
#### 输入格式
5+
6+
共两行,每行包含一个整数。
7+
8+
#### 输出格式
9+
10+
共一行,包含所求的和。
11+
12+
#### 数据范围
13+
14+
$1 \le 整数长度 \le 100000$
15+
16+
#### 输入样例:
17+
18+
12
19+
23
20+
21+
22+
#### 输出样例:
23+
24+
35
25+
26+
---
27+
### 算法
28+
29+
高精度加法模板题
30+
31+
时间复杂度: $O(n)$,$n$ 是两个数字的长度最大值。
32+
33+
空间复杂度: $O(n)$
34+
#### C++ 代码
35+
```cpp
36+
#include <iostream>
37+
#include <vector>
38+
39+
using namespace std;
40+
41+
vector<int> add(vector<int>& A, vector<int>& B)
42+
{
43+
vector<int> C;
44+
int t = 0;
45+
46+
for (int i = 0; i < A.size() || i < B.size() || t; i ++ ) {
47+
if (i < A.size()) t += A[i];
48+
if (i < B.size()) t += B[i];
49+
C.push_back(t % 10);
50+
t /= 10;
51+
}
52+
53+
return C;
54+
}
55+
56+
int main()
57+
{
58+
string a, b;
59+
cin >> a >> b;
60+
61+
vector<int> A, B;
62+
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
63+
for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');
64+
65+
auto C = add(A, B);
66+
67+
string res;
68+
for (int i = C.size() - 1; i >= 0; i -- ) res += to_string(C[i]);
69+
cout << res << endl;
70+
71+
return 0;
72+
}
73+
```
74+
注释版
75+
```cpp
76+
#include <iostream>
77+
#include <vector>
78+
79+
using namespace std;
80+
81+
// C = A + B
82+
// &:表示传入的是原 vector 的地址,操作的就是同一个空间
83+
// 无需复制,省去复制一份的空间和时间
84+
vector<int> add(vector<int> &A, vector<int> &B)
85+
{
86+
// 定义存储结果的 vector
87+
vector<int> C;
88+
89+
// 记录进位,取值为 0 或 1,0 表示没有进位,1 表示有进位
90+
// 同时还用于记录每一位计算后的中间结果
91+
int t = 0;
92+
for (int i = 0; i < A.size() || i < B.size(); i++)
93+
{
94+
// 每次 t += A[i] 或者 B[i],都会加上 t,t 表示进位
95+
// 如果有进位就相当于 + 1,没有进位就相当于没加
96+
97+
// 如果 A[i] 这一位有数字,就加上
98+
if (i < A.size()) t += A[i];
99+
// 如果 B[i] 这一位有数字,就加上
100+
if (i < B.size()) t += B[i];
101+
102+
// 如果 t >= 10 表示有进位,就把 t 的个位数存入 vector,进位加到高位上,
103+
// 同时 t /= 10 -> t = 1,表示有进位
104+
// 如果 t < 10 就表示没有进位,直接把个位数 t 存入 vector
105+
// 同时 t /= 10 -> t = 0,表示没进位
106+
C.push_back(t % 10);
107+
t /= 10;
108+
}
109+
110+
// 如果最高位求和之后有进位,则把进位 1 加入到 vector 中
111+
if (t) C.push_back(1);
112+
113+
return C;
114+
}
115+
116+
int main()
117+
{
118+
// 用来读入两个大整数
119+
string a, b;
120+
// 定义两个向量用来分别存储两个大整数的每一位数
121+
vector<int> A, B;
122+
123+
cin >> a >> b;
124+
// 将两个大整数的每一位从低位到高位依次加入到 vector 中
125+
for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
126+
for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
127+
128+
// auto 是类型推断,通过返回值的类型而确定,此处为 vector<int>
129+
// C 就是 A + B 的结果
130+
auto C = add(A, B);
131+
132+
// 输出结果
133+
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
134+
135+
return 0;
136+
}
137+
```
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
### 题目描述
2+
给定两个正整数(不含前导 $0$),计算它们的差,计算结果可能为负数。
3+
4+
#### 输入格式
5+
6+
共两行,每行包含一个整数。
7+
8+
#### 输出格式
9+
10+
共一行,包含所求的差。
11+
12+
#### 数据范围
13+
14+
$1 \le 整数长度 \le 10^5$
15+
16+
#### 输入样例:
17+
18+
32
19+
11
20+
21+
22+
#### 输出样例:
23+
24+
21
25+
26+
---
27+
### 算法
28+
29+
高精度减法模板题
30+
31+
时间复杂度: $O(n)$,$n$ 是两个数字的长度最大值。
32+
33+
空间复杂度: $O(n)$
34+
#### C++ 代码
35+
```cpp
36+
#include <iostream>
37+
#include <vector>
38+
39+
using namespace std;
40+
41+
// A >= B ?
42+
bool cmp(vector<int>& A, vector<int>& B)
43+
{
44+
if (A.size() > B.size()) return true;
45+
else if (A.size() < B.size()) return false;
46+
else {
47+
for (int i = A.size() - 1; i >= 0; i -- ) // 从高位到低位比较
48+
if (A[i] != B[i])
49+
return A[i] > B[i];
50+
return true; // 两个数相等
51+
}
52+
}
53+
54+
// 保证 A > B
55+
vector<int> sub(vector<int>& A, vector<int>& B)
56+
{
57+
vector<int> C;
58+
int t = 0;
59+
60+
for (int i = 0; i < A.size(); i ++ ) {
61+
t = A[i] - t;
62+
if (i < B.size()) t -= B[i];
63+
C.push_back((t + 10) % 10);
64+
if (t < 0) t = 1; // 如果 t 小于说明有借位,则 t 赋值为 1
65+
else t = 0;
66+
}
67+
68+
while (C.size() > 1 && C.back() == 0) C.pop_back(); // 去除前导 0
69+
return C;
70+
}
71+
72+
int main()
73+
{
74+
string a, b;
75+
cin >> a >> b;
76+
77+
vector<int> A, B;
78+
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
79+
for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');
80+
81+
vector<int> C;
82+
string res;
83+
if (cmp(A, B)) { // A 大于等于 B
84+
C = sub(A, B);
85+
} else {
86+
C = sub(B, A);
87+
printf("-");
88+
}
89+
for (int i = C.size() - 1; i >= 0; i -- ) res += to_string(C[i]);
90+
cout << res << endl;
91+
92+
return 0;
93+
}
94+
```
95+
注释版
96+
```cpp
97+
#include <iostream>
98+
#include <vector>
99+
100+
using namespace std;
101+
102+
// 判断 a >= b
103+
bool cmp(vector<int> &A, vector<int> &B)
104+
{
105+
// 如果向量 A 的元素个数大于向量 B 的元素个数 -> a > b
106+
if (A.size() > B.size()) return true;
107+
// 如果向量 A 的元素个数小于向量 B 的元素个数 -> a < b
108+
else if (A.size() < B.size()) return false;
109+
// 如果向量 A 的元素个数等于向量 B 的元素个数 有可能 a = b
110+
else // A.size() == B.size()
111+
{
112+
// 从数字的高位依次向低位进行比较
113+
for (int i = A.size() - 1; i >= 0; i--)
114+
// 如果每一位不相等,比较大小
115+
if (A[i] != B[i]) return A[i] > B[i];
116+
// 如果两个数相等,返回 true
117+
return true;
118+
}
119+
}
120+
121+
// C = A - B
122+
// &:表示传入的是原 vector 的地址,操作的就是同一个空间
123+
// 无需复制,省去复制一份的空间和时间
124+
vector<int> sub(vector<int> &A, vector<int> &B)
125+
{
126+
// 定义存储结果的 vector
127+
vector<int> C;
128+
129+
// 记录借位,取值为 0 或 1,0 表示没有借位,1 表示有借位,借 1 相当于 + 10
130+
// 同时还用于记录每一位计算后的中间结果
131+
int t = 0;
132+
// 因为 A.size() >= B.size(),所以只需判断 i < A.size() 即可
133+
for (int i = 0; i < A.size(); i++)
134+
{
135+
// 先计算 A[i] - 借位 的结果
136+
t = A[i] - t;
137+
// 判断 B[i] 是否还有值,有值就相减
138+
if (i < B.size()) t -= B[i];
139+
140+
/*
141+
* 可以简化为 C.push((t + 10) % 10)
142+
*/
143+
// 有借位,+ 10 后再存
144+
if (t < 0) C.push_back(t + 10);
145+
// 没借位直接存
146+
else C.push_back(t);
147+
148+
// 记录每次计算后是否有借位
149+
// 有借位
150+
if (t < 0) t = 1;
151+
// 没借位
152+
else t = 0;
153+
}
154+
155+
// 如果计算结果出现类似 003,需要删除前导 0,才能��到正确的结果
156+
while (C.size() > 1 && C.back() == 0) C.pop_back();
157+
158+
return C;
159+
}
160+
161+
int main()
162+
{
163+
// 用来读入两个大整数
164+
string a, b;
165+
// 定义两个向量用来分别存储两个大整数的每一位数
166+
vector<int> A, B;
167+
168+
cin >> a >> b;
169+
// 将两个大整数的每一位从低位到高位依次加入到 vector 中
170+
for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
171+
for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
172+
173+
// auto 是类型推断,通过返回值的类型而确定,此处为 vector<int>
174+
// 如果向量 A 表示的数 a > 向量 B 表示的数 b,直接计算 A - B
175+
if (cmp(A, B))
176+
{
177+
auto C = sub(A, B);
178+
// 输出结果
179+
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
180+
}
181+
// 否则,计算 B - A,输出时添一个负号即可
182+
else
183+
{
184+
auto C = sub(B, A);
185+
// 输出结果
186+
printf("-");
187+
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
188+
}
189+
190+
return 0;
191+
}
192+
```

0 commit comments

Comments
 (0)