本文出自我的掘金博客, 欢迎大家访问!
- 一开始其实是用java写算法的, 后来由于某些原因又成了一名C++选手, 高精度的题目本来可以用java的高精度运算类水过去, 但为了自己的编码能力着想, 还是用C++的数组实现了一遍高精度运算, 下面我将
认真的整理一下具体应该怎样用C++实现高精度运算(主要还是来源于几个大牛写的题解, 我自己写的基本代码丑且难看555QwQ)
高精度加法
要点: 首先要将低位放在数组的头部, 其次就是要注意进位, 然后就是模仿小学的列竖式计算喽!
这里强调一下预处理的步骤, 即读入这么一个大数, 你可以用
C++
中的string
, 也可以用c
中的char []
数组, 其实都是一样的, 感觉我自己没有讲清楚, 我还是来给一给具体的实现作一下参考吧.
//用string
string str1, str2;
cin >> str1 >> str2;
这时你已经将这两个数以字符串的形式存起来了, 然后你就可以从字符串的最后面进行计算
string add(string str1,string str2)//高精度加法
{
string str;
int len1=str1.length();
int len2=str2.length();
//前面补0,弄成长度相同
if(len1<len2)
{
for(int i=1;i<=len2-len1;i++)
str1="0"+str1;
}
else
{
for(int i=1;i<=len1-len2;i++)
str2="0"+str2;
}
len1=str1.length();
int cf=0;
int temp;
for(int i=len1-1;i>=0;i--)
{
temp=str1[i]-'0'+str2[i]-'0'+cf;
cf=temp/10;
temp%=10;
str=char(temp+'0')+str;
}
if(cf!=0) str=char(cf+'0')+str;
return str;
}
- 第二种借助于
char []
数组的写法我更推荐一些
char a[50001], a1[50001];
cin >> a1;
a[0] = strlen(a1);
for (int i = 1; i <= a[0]; i++) {
a[i] = a1[a[0] - i] - '0';
}
高精度减法
对于高精度减法而言就要复杂很多, 首先你得考虑可能是一个小数减去一个大数的问题, 其次你得考虑借位的问题, 最后你要考虑去除前导0的问题, 比如10001 - 10000 = 00001
你得去除这几个前导0, 最后, 你还得注意0 应该输出0;
#include <bits/stdc++.h>
using namespace std;
int a[10100], b[10100], res[10100], maxl;
bool flag = false;//这个是同来标记是否需要加负号
//这个函数的作用是用来判断减数与被减数谁大
int cmp (string str1, string str2) {
if (str1.length() > str2.length()) {
return 1;
} else if (str1.length() < str2.length()) {
return -1;
} else {
return str1.compare(str2);
}
}
string sub(string str1, string str2) {
string str;
int cf = 0; //用来标记是否借位
int tmp = str1.length() - str2.length();
for (int i = str2.length() - 1; i >= 0; i--) {
if (str1[tmp + i] < str2[i] + cf) {
str = char(str1[tmp + i] - str2[i] - cf + '0' + 10) + str;
cf = 1;
} else {
str = char(str1[tmp + i] - str2[i] - cf + '0') + str;
cf = 0;
}
}
for (int i = tmp - 1; i >= 0; i--) {
if (str1[i] - cf >= '0') {
str = char(str1[i] - cf) + str;
cf = 0;
} else {
str = char(str1[i] - cf + 10) + str;
cf = 1;
}
}
str.erase(0,str.find_first_not_of('0'));//去除结果中多余的前导0
return str;
}
int main() {
string a;
string b;
cin >> a >> b;
if (cmp(a, b) == 0) {
cout << 0 << endl;
} else if (cmp(a, b) < 0) {
swap(a, b);
cout << '-' << sub(a, b) << endl;
} else {
cout << sub(a, b) << endl;
}
return 0;
}
高精度乘法
这个需要注意的地方也是前导0和进位而已, 这里介绍一个下处理技巧, 考虑我们平时的竖式乘法, 我们会发现对于乘数1
的第i
位与乘数2
的第j
位相乘会对结果的第i + j - 1
位作出贡献, 这么说吧, 结果的第k
位是两个乘数的第i
与j
位(满足i + j - 1 == k
)作出贡献(先不考虑进位的问题)用代码描述是这样的
for (i=1;i<=a[0];++i)for (j=1;j<=b[0];++j)c[i+j-1]+=a[i]*b[j];
考虑进位后整体的代码是这样的
#include<iostream>
#include<cstring>
using namespace std;
char a1[50001],b1[50001];
int a[50001],b[50001],i,x,len,j,c[50001];
int main ()
{
cin >>a1 >>b1;//读入两个数
a[0]=strlen(a1);b[0]=strlen(b1);//计算长度
for (i=1;i<=a[0];++i)a[i]=a1[a[0]-i]-'0';//将字符串转换成数字
for (i=1;i<=b[0];++i)b[i]=b1[b[0]-i]-'0';
for (i=1;i<=a[0];++i)for (j=1;j<=b[0];++j)c[i+j-1]+=a[i]*b[j];//按乘法
len=a[0]+b[0]; //原理进行高精乘
for (i=1;i<len;++i)if (c[i]>9){c[i+1]+=c[i]/10;c[i]%=10;}//进位
while (c[len]==0&&len>1)len--;//判断位数
for (i=len;i>=1;--i)cout <<c[i];//输出
return 0;
}
上述代码来源于神犇的题解, 蒟蒻仅作整理, 希望能帮助您!