一.什么时候使用高精度算法
概念:在我们进行计算的过程中,经常会遇到几十位,甚至几百位的数字的计算问题,也有可能会遇到小数点后几十位,几百位的情况,而我们面对这样的情况下, 和
的数据范围显然是不够使用的了。因此这时,我们就需要引入一个新的算法,叫做高精度算法 .
这里补充一下 : int 2E9 、long long 9E18;
思想: 高精度算法本质上是用字符串模拟数字进行计算,再利用类似于数学里的竖式的形式,一位一位进行相关计算
二.如何去使用高精度算法
高精度计算中需要处理好以下几个问题:
1)数据的接收方法和存储方法
数据的接收和存储:当输入的数很长时,可采用字符串方式输入,这样可输入位数很长的数,利用字符串函数和操作运算,将每一位取出,存入数组中 .
void init(int a[]) { // 传入数组 string s; cin >> s; len = s.length(); // s.length --> 计算字符串位数 for(int i=1; i<=len; i++) a[i] = s[len -i] - '0'; //将字符串s转换为数组a, 倒序存储 }
2.1)进位、错位处理(加法)
int carry = 0;//定义一个变量实现进位处理 int len_c = 1; // 这里注意len_c最开始是1 while(len_c <= len_b || len_c <= len_a){ // 两数相加一定不能超过最大数数位加1 c[len_c] = a[len_c] + b[len_c] + carry; carry = c[len_c] / 10;// 如果c[len_c]超10了就赋给carry实现进位 c[len_c] = c[len_c] % 10; len_c++; // 错位处理 } carry = c[len_c]; // 出现比最大位大的情况 if(carry == 0){ //消去前导0 len_c--; }
2.1)基本代码(加法)
#include<bits/stdc++.h> using namespace std; #define N 10005 #define int long long int a[N],b[N],c[N],len_a,len_b,len_c=1; // 数据的接收、储存的办法 void init(){ string s1,s2; getline(cin,s1); getline(cin,s2); len_a = s1.length(); len_b = s2.length(); for (int i = 1;i <= len_a;++i){ a[i] = s1[len_a-i] - '0'; } for (int i = 1;i <= len_b;++i){ b[i] = s2[len_b-i] -'0'; } } void myadd(){ int carry = 0; while(len_c <= len_a || len_c <= len_b){ c[len_c] = a[len_c] + b[len_c] + carry; carry = c[len_c]/10; c[len_c] = c[len_c]%10; len_c++; } carry = c[len_c]; if(carry == 0){ len_c--; } } void print(){ for (int i = len_c;i >= 1;i--){ cout << c[i]; } } signed main(){ init(); myadd(); print(); return 0; }
2.2)进位、错位处理(减法)
// 减法就多一个借位处理的问题 while(len_c <= len_b || len_c <= len_a){ if(a[i]<b[i]){ c[i] = a[i] + 10 - b[i]; a[i+1]--; } else{ c[i] = a[i] - b[i]; } len_c++; }
2.2)基本代码(减法)
#include<bits/stdc++.h> using namespace std; #define N 10005 #define int long long int a[N],b[N],c[N],len_a,len_b,len_c=1; // 数据的接收、储存的办法 void init(){ string s1,s2; getline(cin,s1); getline(cin,s2); len_a = s1.length(); len_b = s2.length(); for (int i = 1;i <= len_a;++i){ a[i] = s1[len_a-i] - '0'; } for (int i = 1;i <= len_b;++i){ b[i] = s2[len_b-i] -'0'; } } void myjian(){ while(len_c <= len_a || len_c <= len_b){ if(a[len_c] < b[len_c]){ c[len_c] = a[len_c] + 10 - b[len_c]; a[len_c+1]--; } else{ c[len_c] = a[len_c] - b[len_c]; } len_c++; } while(c[len_c] == 0 && len_c > 1){ len_c--; } } void print(){ for (int i = len_c;i >= 1;i--){ cout << c[i]; } } signed main(){ init(); myjian(); print(); return 0; }
2.3)进位、错位处理(乘法)
//从低位到高位 累加乘积 进位 存余 for (int i = 1;i <= len_a;i++){ for (int j = 1;j <= len_b;j++){ c[i+j-1] += a[i]*b[j]; // 累加乘积 c[i+j] += c[i+j] / 10; // 进位 c[i+j-1] %= 10; // 存余数 } } //去除前导0 while(len_c>1 && c[len_c]==0){ len_c--; }
2.3) 基本代码(乘法)
#include<bits/stdc++.h> using namespace std; #define N 10005 #define int long long int a[N],b[N],c[N],len_a,len_b,len_c=1; // 数据的接收、储存的办法 void init(){ string s1,s2; getline(cin,s1); getline(cin,s2); len_a = s1.length(); len_b = s2.length(); for (int i = 1;i <= len_a;++i){ a[i] = s1[len_a-i] - '0'; } for (int i = 1;i <= len_b;++i){ b[i] = s2[len_b-i] -'0'; } } void myadd(){ int carry = 0; while(len_c <= len_a || len_c <= len_b){ c[len_c] = a[len_c] + b[len_c] + carry; carry = c[len_c]/10; c[len_c] = c[len_c]%10; len_c++; } carry = c[len_c]; if(carry == 0){ len_c--; } } void myjian(){ while(len_c <= len_a || len_c <= len_b){ if(a[len_c] < b[len_c]){ c[len_c] = a[len_c] + 10 - b[len_c]; a[len_c+1]--; } else{ c[len_c] = a[len_c] - b[len_c]; } len_c++; } while(c[len_c] == 0 && len_c > 1){ len_c--; } } void mymul(){ len_c = len_a + len_b; for (int i = 1;i <= len_a;i++){ for (int j = 1;j <= len_b;j++){ c[i+j-1] += a[i]*b[j]; c[i+j] += c[i+j]/10; c[i+j-1] %= 10; } } while(len_c > 1&&c[len_c]==0){ len_c--; } } void print(){ for (int i = len_c;i >= 1;i--){ cout << c[i]; } } signed main(){ init(); //myadd(); //myjian(); mymul(); print(); return 0; }