P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
“用原始的方法模拟计算,有品。”
当语言的基本数学数据类型存放不了一个数字,就应该考虑高精度了。
目录
P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
高精度加法
5 | 1 | 2 | ||
+ | 5 | 4 | 8 | |
= | 1 | 0 | 6 | 0 |
想要实现加法,我们需要三个东西,加数,被加数,进位数。加数加被加数加上进位数mod10就是该位的答案。例如上面的第一位和第二位,第一位是(2+8+0)%10得到该位的答案是0,第二位是(1+4+1)%10得到该位的答案是6。故在代码里面我们的实现思路也是如此。
既然基本的数学数据类型存放不了数字,那我们就用先字符串去存放一个数字,然后再拆分成一个数组。高精度加法第一步就是用字符串保存数字,然后转化为数字数组。
cin >> a;
cin >> b;
// a和b为字符串string
for (int i = 0; i < a.length(); i++)
{
ra[i] = a[a.length() - i - 1] - '0';
}
//a如果是"123"
//那么ra里面放的就是321
for (int i = 0; i < b.length(); i++)
{
rb[i] = b[b.length() - i - 1] - '0';
}
//同时将数字反转
//方便后续的加法模拟
//因为加法是从低位开始加的
高精度加法第二步就是模拟加法。按之前说的加数加上被加数加上进位数mod10。
int len = max(a.length(), b.length());
//for循环的次数
//需要按照大的数字长度来进行加法
//123+12
//就是需要循环加3次
for (int i = 0; i < len; i++)
{
c[i] += ra[i] + rb[i];
//加数加被加数加进位数
c[i + 1] = c[i] / 10;
//更新下一位的进位数
c[i] = c[i] % 10;
//mod10得到该位的结果
}
高精度加法第三步考虑前导零。因为600+600的结果是1200,如果你不考虑前导零,那么最后的输出结果就会是200,而不是1200。
while (c[len] != 0)
{
len++;
}
全部代码
#include <iostream>
#include <string>
using namespace std;
const int N = 1e3;
string a, b;
int ra[N], rb[N], c[N];
int main()
{
cin >> a;
cin >> b;
for (int i = 0; i < a.length(); i++)
{
ra[i] = a[a.length() - i - 1] - '0';
}
for (int i = 0; i < b.length(); i++)
{
rb[i] = b[b.length() - i - 1] - '0';
}
int len = max(a.length(), b.length());
for (int i = 0; i < len; i++)
{
c[i] += ra[i] + rb[i];
c[i + 1] = c[i] / 10;
c[i] = c[i] % 10;
}
while (c[len] != 0)
{
len++;
}
for (int i = 0; i < len; i++)
cout << c[len - i - 1];
return 0;
}
P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
“这世上本没有路,走的人多了,也便成了路。”
高精度乘法
1 | 2 | 3 | ||
X | 1 | 2 | ||
=> | 2 | 4 | 6 | |
=> | 1 | 2 | 3 | |
= | 1 | 4 | 7 | 6 |
高精度乘法与加法第一步是一致的。读取字符串并拆分反转成数组。因为都是从低位开始进行运算操作的。
cin >> a;
cin >> b;
for (int i = 0; i < a.length(); i++)
{
ra[i] = a[a.length() - i - 1] - '0';
}
for (int i = 0; i < b.length(); i++)
{
rb[i] = b[b.length() - i - 1] - '0';
}
高精度乘法第二步就是乘法模拟了。
int len = a.length() + b.length();
for (int i = 0; i < a.length(); i++)
for (int j = 0; j < b.length(); j++)
{
c[i + j] += ra[i] * rb[j];
//乘数乘以被乘数 加上进位数
c[i + j + 1] += c[i + j] / 10;
//更新下一位的进位数
c[i + j] = c[i + j] % 10;
//取模得到该位的答案
}
// c[1]在循环中会出现两次
//一次是i=0 j=1
//一次是i=1 j=0
//就好比是
// 123
// 12
//-----
// 246
//123
//-----
//1476
//c[1]出现了两次
//第一次是246中的4
//第二次是123中的3
//两次相加取模进位就是该位的答案7
高精度乘法最后就是去除前导零。一定要注意len>1,因为零乘以任何数都等于零,结果如果本身就是零,就要保留了。
while (c[len - 1] == 0 && len > 1)
{
len--;
}
全部代码
#include <iostream>
#include <string>
using namespace std;
const int N = 1e5;
string a, b;
int ra[N], rb[N], c[N];
int main()
{
cin >> a;
cin >> b;
for (int i = 0; i < a.length(); i++)
{
ra[i] = a[a.length() - i - 1] - '0';
}
for (int i = 0; i < b.length(); i++)
{
rb[i] = b[b.length() - i - 1] - '0';
}
int len = a.length() + b.length();
for (int i = 0; i < a.length(); i++)
for (int j = 0; j < b.length(); j++)
{
c[i + j] += ra[i] * rb[j];
c[i + j + 1] += c[i + j] / 10;
c[i + j] = c[i + j] % 10;
}
while (c[len - 1] == 0 && len > 1)
{
len--;
}
for (int i = 0; i < len; i++)
cout << c[len - i - 1];
return 0;
}
“居然用python都不能逃课,python还是有极限的。”
高精度a的b次方
0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 2 |
0 | 0 | 0 | 0 | 4 |
0 | 0 | 0 | 0 | 8 |
0 | 0 | 0 | 1 | 6 |
上面就是求2的4次方的过程。我们先开一个数组最后一位放1,该数组就相当于是1。然后for循环指数次即4次,让数组中的每个数都乘以底数2,然后如果数组里面有数字是大于等于10的,就取模,进位。
全部代码
#include <iostream>
using namespace std;
const int N = 1e3;
int num[N];
int a, b;
int main()
{
cin >> a;
cin >> b;
num[N - 1] = 1;
for (int i = 0; i < b; i++)
{
for (int i = 0; i < N; i++)
{
num[i] *= a;
}
for (int i = N - 1; i >= 0; i--)
{
if (num[i] >= 10)
{
num[i - 1] += num[i] / 10;
num[i] = num[i] % 10;
}
}
}
int index = 0;
while (num[index] == 0 && index < N - 1)
{
index++;
}
for (int i = index; i < N; i++)
cout << num[i];
return 0;
}