高精度大数处理
背景
当我们在使用c或者c++时,当一个整数值超过了long long 后就无法再运用普通的运算方法了。而是要使用数组类模拟大数运算。
如(洛谷)爬楼梯,中当楼梯数很大时爬楼的方法就会以爆炸增长的趋势最后爆出long long的范围,因此在加每种算法时就要用到大数数组的高精度的方式去记录最后的方法数。
高精度大数的加减
高精度大数的加减可以直接用数组模拟
大数加法函数
int num1[1005], num2[1005]; //将要相加的两数分别放进两个数组中
string add(string a, string b) {//通过字符串来模拟
int lena = a.size(), lenb = b.size();
for (int i = 0; i < lena; i++)
num1[lena - 1 - i] = a[i] - '0'; //把字符转成数字,然后翻转,使na[0]是最低位
for (int i = 0; i < lenb; i++)
num2[lenb - 1 - i] = b[i] - '0';
int lmax = lena > lenb ? lena : lenb;
for (int i = 0; i < lmax; i++) {
num1[i] += num2[i];
num1[i + 1] += num1[i] / 10; //处理进位
num1[i] %= 10;
}
if (num1[lmax]) lmax++; //若最高位相加后也有进位,数字长度加1
string ans;
for (int i = lmax - 1; i >= 0; i--) //把数字转成字符,然后翻转
ans += num1[i] + '0';
return ans;
}
大数减法函数
int na[1005],nb[1005]; //被减数和减数
string sub(string a,string b){
if(a == b) return "0"; //特判一下是否两数字相等
bool neg = 0; //标记是否为负数
if(a.size() < b.size() || a.size() == b.size() && a < b)
swap(a, b), neg = 1; //让a大于b
int lena=a.size(),lenb=b.size();
for(int i=0;i<lena;i++) //把字符转成数字,然后翻转,使na[0]是最低位
na[lena-1-i]=a[i]-'0';
for(int i=0;i<lenb;i++)
nb[lenb-1-i]=b[i]-'0';
int lmax = lena;
for(int i=0;i<lmax;i++){
na[i] -= nb[i];
if(na[i]<0){ //处理借位
na[i]+=10;
na[i+1]--;
}
}
while(!na[--lmax] && lmax>0) //找到首位为0的位置
; //什么都不做
lmax++;
string ans;
for(int i=lmax-1;i>=0;i--) //把数字转成字符,然后翻转
ans += na[i]+'0';
if(neg) ans = "-" + ans; //查询一下是否为负数
return ans;
}
大数乘法函数
int na[1005], nb[1005], nc[1000005];
string mul(string a,string b){
if(a=="0"||b=="0") return "0";
int lena=a.size(),lenb=b.size();
for(int i=0;i<lena;i++)
na[lena-i]=a[i]-'0';
for(int i=0;i<lenb;i++)
nb[lenb-i]=b[i]-'0';
for(int i=1;i<=lena;i++)
for(int j=1;j<=lenb;j++)
nc[i+j-1] += na[i]*nb[j];
for(int i=1;i<=lena+lenb;i++)
nc[i+1]+=nc[i]/10,nc[i]%=10;
string ans;
if(nc[lena+lenb]) ans += nc[lena+lenb]+'0';
for(int i=lena+lenb-1;i>=1;i--) ans += nc[i]+'0';
return ans;
}
大数除法函数
算法核心:逐位试商法(同余定理)
①从被除数的第一位开始,用此数除以除数,得出商和余数
②用得出的余数与被除数的下一位数字结合继续除以除数,以此类推
1、高精度除以低精度
//高精度除法(高精度除于低精度)
#include <iostream>
using namespace std;
const int N = 1e5 + 5;
int a[N], ans[N], b, x;//b为低精度除数,x为截数所得
int main() {
string s;
cin >> s >> b;
for (int i = 1;i <= s.size();i++)
a[i] = s[i - 1] - '0';//因为是除法,不会溢出,所以正向存储
for (int i = 1;i <= s.size();i++)
{
x = x * 10 + a[i];//截数
ans[i] = x / b;//存答案
if (x >= b)x = x % b;//如果>=b,更新x
}
int begin = 1;
while (!ans[begin])begin++;//去除前导0
for (int i = begin;i <=s.size();i++)
cout << ans[i];//输出商
cout << endl << x << endl;//输出x(x即为余数)
return 0;
}
声明
部分代码转载自:https://blog.csdn.net/weixin_43914593/article/details/134386824