今天,我就来写一个关于高精度算法的总结,首先,我们要知道C++为什么要用到高精度算法,首先我们知道,C++中最大的整数类型就是long long ,最大范围是10的18次方,但是如果超过了10的18次方怎么办,存都存不下,更别谈运算了,这种数被称为高精度数和大整数!
先给大家说一下高精度的名词:
低精:
直接可以使用 C++ 中有的数据类型进行定义。比如 15,678,808,877 这个数,我们可以用 long long 来定义。
高精加高精:
高精度数加上高精度数。
高精乘高精:
高精度数乘上高精度数。
高精乘低精:
高精度数乘上低精度数。
高精除高精:
高精度数除以高精度数。
高精除低精:
高精度数除以低精度数。
高精度加法
接下来,我们就可以正式开始高精度运算了,我们先从高精度加法算起,我们在小学二三年级的时候,做一些加法题都需要用到竖式计算,而这种竖式计算是无论多大的数都可以算出来的,所以我们可以借助模拟竖式计算的方法来进行高精度加法运算。
思路:
-
定义存储数组。
-
读入数据到数组中。注意是倒序存放,也就是个位放在数组下标为 0 的地方。
-
从个位开始模拟竖式加法的过程,完成整个加法。
-
删除前导 0 。所谓前导零,就是出现类似这样数据 01234,这个 0 实际是不需要的。
-
输出加法的结果。倒序输出加法的结果数组 C,因为我们的个位是存储在下标为 0 的地方。
我们先来看一看存储结构:
const int N=1e5+10;
char s1[N]={};//存储字符串
char s2[N]={};//存储字符串
int a[N]={};//存储加数A
int b[N]={};//存储加数B
int c[N]={};//存储和C
读入数据:
我们先输入s1,s2两个字符串,然后再求出两个字符串的长度l1和l2,之后将s1[i]赋值给a[i],将s2[i]赋值给b[i],用int类型数组更容易计算一些!
scanf("%s %s",s1,s2);
int l1=strlen(s1);
int l2=strlen(s2);
for(int i=0;i<l1; i++)
a[i]=s1[l1-i-1]-'0';
for(int i=0;i<l2;i++)
b[i]=s2[l2-i-1]-'0';
模拟竖式加法:
首先,我们要将a[i]和b[i]加起来,存到c[i]里面,在将他们的进位存在jw里面,每次运算加上去,哪怕是0,之后再将c[i]对10来取模,是求进位过后这个位是什么数字!
//模拟竖式加法
int jw=0;//进位
int l=max(l1,l2)+1;//注意因为最高位可能出现进位
for(int i=0;i<len;i++)
{
c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
jw=c[i]/10;//本次加法是否存在进位
c[i]%=10;//只能保存0~9的数据
}
有两个细节需要注意:
-
进位如何保存;
-
最高位进位如何解决。
删除多余的0:
由于我们是倒着来的前面有很多多余的0,我们用for循环倒着删除,如果遇到0了,就将c[i]的长度减1,直到碰见第一个不是0的最高位,就break;结束删除!
//删除前导零
for (int i=l-1;i>=0;i--)
{
//因为我们是从下标0开始,所以最高位是保存在l-1
if(0==c[i]&&l>1)
{
//注意要有 l>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
len--;
}
else
{
//第一个不是零的最高位,结束删除
break;
}
}
输出计算结果:
最后就是将计算结果输出就行了,用for循环一个一个来打印!
//逆序打印输出
for (int i=l-1;i>=0;i--)
{
printf("%d",c[i]);
}
printf("\n");
高精度加法的完整代码:
#include <bits/stdc++.h>
using namespace std;
const int N=200+4;
char s1[N]={};//存储字符串
char s2[N]={};//存储字符串
int a[N]={};//存储加数A
int b[N]={};//存储加数B
int c[N]={};//存储和B
int main()
{
scanf("%s %s",s1,s2);//读入字符串A
//将字符串写入到数组A中
int l1=strlen(s1);
for(int i=0;i<l1;i++)
{
//倒序写入
a[i]=s1[len1-i-1]-'0';
}
//将字符串写入到数组A中
int l2=strlen(s2);
for(int i=0;i<len2;i++)
{
//倒序写入
b[i]=s2[len2-i-1]-'0';
}
//模拟竖式加法
int jw=0;//进位
int l=max(l1,l2)+1;//注意因为最高位可能出现进位
for(int i=0;i<l;i++)
{
c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
jw=c[i]/10;//本次加法是否存在进位
c[i]%=10;//只能保存 0 ~ 9 的数据
}
//删除前导零
for(int i=l-1;i>=0;i--) {
//因为我们是从索引 0 开始,所以最高位是保存在 len-1
if(0==c[i]&&len>1)
{
//注意要有 len>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
l--;
}
else
{
//第一个不是零的最高位,结束删除
break;
}
}
//逆序打印输出
for (int i=l-1; i>=0; i--)
{
printf("%d", c[i]);
}
printf("\n");
return 0;
}
高精度减法
高精度减法计算原理
在读小学时,我们做减法都采用竖式方法,如图 1 所示。这样,我们可以写出两个整数相减的算法。
编辑
我们就可以用 C++ 语言来模拟这个竖式减法的过程。我们可以考虑利用 C++ 的数组来存储对应数据,假设用数组 A 存储被减数 856 的每一位,具体来说就是 A1 存储个位 6,A2 存储十位 5,A3存储百位 8;类似数组 A 的结构,使用数组 B 存储减数 257;类似数组 A 的结构,使用数组 C 来存储对应的差 5