大数加法:
原题连接
对于一些范围比较小的数据,利用C/C++自带的数据类型就可以解决。但是对于一些数据比如10^1000000这样的数据,我们如何处理呢?
这时,我们就要用到大数运算了。
大数运算的根本在于要用字符串或是数组对每一位进行保存。下面介绍一下大数加法。由于大数加法比较简单,我们直接对字符串进行操作,不在用数组了。
第一步是以字符串的形式输入两个整数
string a, b;
cin >> a >> b;
string resa = a;
string resb = b;
for (int i = 0; i < a.size(); i++)
resa[i] = a[a.size() - 1 - i];
for (int i = 0; i < b.size(); i++)
resb[i] = b[b.size() - 1 - i];
int maxSize = a.size() > b.size() ? a.size() : b.size();
resa,resb是a,b的反转字符串。为什么反转?我们模拟一下我们做加法,是列一个竖式从个位加到最高位。所以我们反转一下字符串便于运算。
string ans;
int i = 0, j = 0;
bool flag = 0;
while (resa[i] != '\0'|| resb[j] != '\0') {
if (resa[i] != '\0' && resb[j] != '\0') {
int x = resa[i] + resb[j] - '0' - '0' + flag;
if (x >= 10) {
ans.push_back(x % 10 + '0');
flag = 1;
}
else {
ans.push_back(x + '0');
flag = 0;
}
i++;
j++;
}
这里有几个变量ans是答案,flag是进位(因为进位不可能为2,所以我们直接用bool变量),因为可能存在要进位的情况。接下来进入循环。循环的终止条件是什么呢?就是两个字符串都加到最高位了,也就是此时为’\0’状态。那么我们考虑一下可能存在的情况。第一种情况:两个字符串都没有到达最高位。int x = resa[i] + resb[j] - ‘0’ - ‘0’ + flag这条语句就是就是计算此时该位相加的结果,注意要减去’0’,而且要加上进位的结果。如果x>=10说明要进位了,我们在ans后添加x的各位数字(要加上’0’),并把flag赋值为1,代表要进位;否则就直接把x添加上去,flag赋值为。然后i++,j++,移动至下一个字符。
else if (resa[i] != '\0' && resb[j] == '\0') {
int x = resa[i] - '0'+ flag;
if (x >= 10) {
ans.push_back(x % 10 + '0');
flag = 1;
}
else {
ans.push_back(x + '0');
flag = 0;
}
i++;
}
else {
int x = resb[j] - '0' + flag;
if (x >= 10) {
ans.push_back(x % 10 + '0');
flag = 1;
}
else {
ans.push_back(x + '0');
flag = 0;
}
j++;
}
我们想,加法会有两个数位数不一致的情况。那么还需要处理一下这种情况。但其实实质与两位相加相同。这可以理解为其中一位为零。
if (flag)
ans.push_back('1');
for (int i = ans.size() - 1; i >= 0; i--)
cout << ans[i];
当然还有一种情况,举个栗子,50+50,最后肯定要再添一位。但是在循环中有进位有延后。所以我们还要再判断一下是否要进位。最后逆序输出。
完整代码:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a, b;
cin >> a >> b;
string resa = a;
string resb = b;
for (int i = 0; i < a.size(); i++)
resa[i] = a[a.size() - 1 - i];
for (int i = 0; i < b.size(); i++)
resb[i] = b[b.size() - 1 - i];
int maxSize = a.size() > b.size() ? a.size() : b.size();
string ans;
int i = 0, j = 0;
bool flag = 0;
while (resa[i] != '\0'|| resb[j] != '\0') {
if (resa[i] != '\0' && resb[j] != '\0') {
int x = resa[i] + resb[j] - '0' - '0' + flag;
if (x >= 10) {
ans.push_back(x % 10 + '0');
flag = 1;
}
else {
ans.push_back(x + '0');
flag = 0;
}
i++;
j++;
}
else if (resa[i] != '\0' && resb[j] == '\0') {
int x = resa[i] - '0'+ flag;
if (x >= 10) {
ans.push_back(x % 10 + '0');
flag = 1;
}
else {
ans.push_back(x + '0');
flag = 0;
}
i++;
}
else {
int x = resb[j] - '0' + flag;
if (x >= 10) {
ans.push_back(x % 10 + '0');
flag = 1;
}
else {
ans.push_back(x + '0');
flag = 0;
}
j++;
}
}
if (flag)
ans.push_back('1');
for (int i = ans.size() - 1; i >= 0; i--)
cout << ans[i];
return 0;
}
大数减法:
原题链接
大数减法与之类似,但略微复杂一些,这里用数组会好处理一些。
const int MAX = 100000;
int main()
{
int a_num[MAX] = { 0 }, b_num[MAX] = { 0 };
string a, b;
cin >> a >> b;
int alen = a.size();
int blen = b.size();
if (alen < blen || alen == blen && a < b) {
swap(a, b);
swap(alen, blen);
cout << "-";
}
for (int i = 0; i < alen; i++) {
a_num[alen - i] = a[i] - '0';
}
for (int i = 0; i < blen; i++) {
b_num[blen - i] = b[i] - '0';
}
与大数加法类似,我们先以字符串形式输入数据。我们要用a_num这个数组储存答案,我们就要判定一下是否要把a,b交换。为什么呢?举个栗子,计算15-20,我们是用20-15再添负号的。所以这就要求a要大于b。a大于b的条件是a的长度小于b,或是长度一样但是a的字典序大于b。当a小于b时,我们就要交换a,b。同时由于a<b,我们要在输出一个负号。然后把a的逆序赋给a_num数组。在这之中,a_num[1]储存的是个位数字。b同理。
for (int i = 1; i <= alen; i++) {
if (a_num[i] < b_num[i]) {
a_num[i] += 10;
a_num[i] -= b_num[i];
a_num[i + 1] -= 1;
}
else
a_num[i] -= b_num[i];
}
然后我们开始逐位处理,如果a_num[i]<b_num[i],我们就需要借位,直接在该位加十,同时下一位减一。否则直接相减就可。
while (a_num[alen] == 0 && alen > 1)
alen--;
for (; alen >= 1; alen--)
cout << a_num[alen];
return 0;
最后输出,但是相减可会导致高位为0,所以要去除所有的0,最后逆序输出即可。
完整代码:
#include<iostream>
#include<string>
using namespace std;
const int MAX = 100000;
int main()
{
int a_num[MAX] = { 0 }, b_num[MAX] = { 0 };
string a, b;
cin >> a >> b;
int alen = a.size();
int blen = b.size();
if (alen < blen || alen == blen && a < b) {
swap(a, b);
swap(alen, blen);
cout << "-";
}
for (int i = 0; i < alen; i++) {
a_num[alen - i] = a[i] - '0';
}
for (int i = 0; i < blen; i++) {
b_num[blen - i] = b[i] - '0';
}
for (int i = 1; i <= alen; i++) {
if (a_num[i] < b_num[i]) {
a_num[i] += 10;
a_num[i] -= b_num[i];
a_num[i + 1] -= 1;
}
else
a_num[i] -= b_num[i];
}
while (a_num[alen] == 0 && alen > 1)
alen--;
for (; alen >= 1; alen--)
cout << a_num[alen];
return 0;
}