目录
在进行计算的过程中,会遇到几十位,甚至几百位的数字的计算问题,也有可能会遇到小数点后几十位的情况,而我们面对这样的情况下,int
、long
、double
等类型的取值范围不足的问题,高精度计算可以解决此类问题。
高精度主要是用在C/C++,Python 是默认无限大的,所以不需要用高精度,JAVA是有库可以调用也是不需要用高精度。
高精度计算本质上是用字符串模拟数字进行计算,再利用类似于数学里的竖式的形式,一位一位进行相关计算 .
1.高精度加法
高精度加法就是完全模拟的加法运算,以加法运算234 + 989为例
2 | 3 | 4 | ||
+ | (1) | 9 (1) | 8 (1) | 9 |
1 | 2 | 2 | 3 |
红色字体表示进位
代码实现如下:
string High_precision_add(string a, string b) {
string ans = "";
vector<int> a_num;
vector<int> b_num;
vector<int> ans_num;
//反着存入a,b
int t = 0;
for (int i = a.size() - 1; i >= 0; i--) a_num.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) b_num.push_back(b[i] - '0');
for (int i = 0; i < a_num.size() || i < b_num.size(); i++) {
if (i < a_num.size()) t += a_num[i];
if (i < b_num.size()) t += b_num[i];
ans_num.push_back(t % 10);
t /= 10;
}
if (t) ans_num.push_back(t);
for (int i = ans_num.size() - 1; i >= 0; i--) {
ans += ans_num[i] + '0';
}
return ans;
}
2.高精度减法
高精度减法就是完全模拟的减法运算,以减法运算234 - 989为例
首先234<989需要变为-(989-234)
9 | 8 | 9 | |
- | 2 | 3 | 4 |
7 | 5 | 5 |
最后加上负号
又例如983 - 234
9 | 8 (-1) | 3 (10) | |
- | 2 | 3 | 4 |
7 | 4 | 9 |
红色字体中带负号的表示借位,无负号表示从前一位借一位的值。
代码实现如下:
string High_precision_sub(string a, string b) {
string ans = "";
if (a == b) {
ans += '0';
return ans;
}//如果ab相等,减法为0
vector<int> a_num;
vector<int> b_num;
vector<int> ans_num;
bool f = true;//判断a,b的大小,如果a>b则为true,否则为false
if (a.size() < b.size()) f = false;//如果a的长度小于b,a的值小于b
else if (a.size() == b.size()) {//当a的长度与b的长度相同时
for (int i = 0; i < a.size(); i++) {//从高位开始比较
if (a[i] != b[i]) {//当遇到不同时
if (a[i] < b[i]) f = false;//a的此位小于b的此位则a小于b
break;
}
}
}//其余情况均为a>b
if (f == false) {
string t = a;
a = b;
b = t;
}//交换a,b
//反着存入a,b
int t = 0;
for (int i = a.size() - 1; i >= 0; i--) a_num.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) b_num.push_back(b[i] - '0');
for (int i = 0; i < a.size(); i++) {
t = a_num[i] - t;
if (i < b_num.size())t = t - b_num[i];
ans_num.push_back((t + 10) % 10);
if (t < 0)t = 1;//表示有借位
else t = 0;
}
if (f == false)ans += '-';
int index;
for (int i = ans_num.size() - 1; i >= 0; i--) {
if (ans_num[i] == 0)continue;
else {
index = i;
break;
}
}
for (int i = index; i >= 0; i--) {
ans += ans_num[i] + '0';
}
return ans;
}
3.高精度乘法
高精度乘法就是完全模拟的乘法运算,以乘法运算234 * 989为例
2 | 3 | 4 | ||||
× | 9 | 8 | 9 | |||
(3)=3 | 6(3)=9 | 2(3)=5 | 6 | |||
(2)=2 | 7(2)=9 | 4(2)=6 | 7 | |||
+ | (1)=1(1) | 8(1)=9(2) | 6(1)=7(2) | 8(1) | ||
2 | 3 | 1 | 4 | 2 | 6 |
红色字体中表示乘法进位,紫色字体表示加法进位。
3.1.高精度乘低精度
代码如下:
string High_precision_mul_Low_precision_mul(string a, int b) {
string ans = "";
vector<int> a_num;
vector<int> ans_num;
//反着存入a
int t = 0;
for (int i = a.size() - 1; i >= 0; i--) a_num.push_back(a[i] - '0');
for (int i = 0; i < a_num.size(); i++) {
t += a_num[i] * b;
ans_num.push_back(t % 10);
t /= 10;
}
while (t) {
ans_num.push_back(t % 10);
t /= 10;
}
for (int i = ans_num.size() - 1; i >= 0; i--) {
ans += ans_num[i] + '0';
}
return ans;
}
3.2.高精度高精度
代码如下:
string High_precision_mul(string a, string b) {
string ans = "";
vector<int> a_num;
vector<int> b_num;
vector<int> ans_num(a.size() + b.size());
//反着存入a,b
int t = 0;
for (int i = a.size() - 1; i >= 0; i--) a_num.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) b_num.push_back(b[i] - '0');
for (int i = 0; i < a_num.size(); i++) {
for (int j = 0; j < b_num.size(); j++) ans_num[i + j] += a_num[i] * b_num[j];
}
for (int i = 0; i < a_num.size() + b_num.size() - 1; i++) {
ans_num[i + 1] += ans_num[i] / 10;
ans_num[i] %= 10;
}//处理进位
int index;
for (int i = a_num.size() + b_num.size() - 1; i >= 0; i--) {
if (ans_num[i] == 0) continue;
else {
index = i;
break;
}
}
for (int i = index; i >= 0; i--) {
ans += ans_num[i] + '0';
}
return ans;
}
4.高精度除以低精度
高精度除低精度,原理是模拟竖式除法,以除法运算234 / 21为例。
2 | 3 | 4 | |
÷ | 21 | ||
商 | 0 | ||
余 | 2 | ||
23 | |||
÷ | 21 | ||
商 | 1 | ||
余 | 2 | ||
24 | |||
÷ | 21 | ||
商 | 1 | ||
余 | 3 | ||
最终: | 商:11 | 余3 |
代码如下:
typedef long long ll;
pair<string, ll> High_precision_div_Low_precision_div(string a, int b) {
pair<string, ll>ans;
ans.first = "";
vector<int> a_num;
vector<int> ans_num;
//顺序存入a
ll r = 0;//r为余数
for (int i = 0; i < a.size(); i++) a_num.push_back(a[i] - '0');
for (int i = 0; i < a_num.size(); i++) {
r = r * 10 + a_num[i];
ans_num.push_back(r / b);
r %= b;
}
ans.second = r;
int index = -1;
for (int i = 0; i < ans_num.size(); i++) {
if (ans_num[i] == 0)continue;
else {
index = i;
break;
}
}
if (index == -1) ans.first += '0';
else for (int i = index; i < ans_num.size(); i++) ans.first += ans_num[i] + '0';
return ans;
}