高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。
part 1 数据的存放与输出
- 以字符串的形式读入数字
- 用数组保存字符串的逐个字符,数组中的第一个用来保存数字的位数(注意代码中数字是倒序储存在数组中,根据具体运算情况来选择是正序还是倒序哦~)
#include <bits/stdc++.h>
using namespace std;
int a[1000],b[1000];
void cun()
{
char a1[1000],b1[1000];
cin>>a1>>b1;
a[0]=strlen(a1);
b[0]=strlen(b1);
for(int i=1;i<=b[0];i++)
{
a[i]=a1[a[0]-i]-'0';
b[i]=b1[b[0]-i]-'0';
}
for(int i=0;i<=a[0];i++)
{
cout<<a[i]<<endl;
}
for(int i=0;i<=b[0];i++)
{
cout<<b[i]<<endl;
}
}
int main()
{
cun();
return 0;
}
part 2 加法运算
- 使用一个变量c来存储加法运算后的可能得到的最大位数——也就是a1和b1中位数较大的数再加1。比如100+9900=10000,位数可能会进一。
- 从最低位到最高位依次相加。同时使用一个变量d来记录可能的进位情况,不进位则为0。
void jiafa()
{
int c,d=0,e,f[1000];
c=a[0]>b[0]?a[0]+1:b[0]+1;
for(int i=1;i<=c;i++)
{
e=b[i]+a[i]+d;//e先存一下各个位上的加数之和再加上进位情况
f[i]=e%10;//存这一位上最终的数字
d=e/10;
}
return;
}
part 3 减法运算
这里仅介绍两数均为非负整数,且已知被减数大于减数的情况辣辣辣辣别的情况类似,不过需要自己加上相应的判断代码块
- 使用一个变量c来存储减法运算后的可能得到的最大位数——也就是被减数的位数。比如10-9=1,位数是1位,比被减数小;而20-1=19,位数与被减数相同。所以最大位数是被减数的位数。
- 从最低位到最高位依次相减。同时使用一个变量d来记录可能的借位情况,不进位则为0,借了一位以后则为-1,加给下面将要计算的一位。
void jianfa()
{
int c,d=0,e,f[1000];
c=a[0];//这里默认a是被减数,b是减数
for(int i=1;i<=c;i++)
{
if(a[i]+d>=b[i])
{
f[i]=a[i]-b[i]+d;
d=0;
}
else
{
f[i]=a[i]+10-b[i]+d;
d=-1;
}
}
return;
}
part 4 乘法运算
根据乘法规律,a的第i位与b的第j位相乘,结果保存在第(i+j-1)位。注意进位的考虑哦~
void chengfa()
{
int c[1000]={0},d;
for(int i=1;i<=a[0];i++)
{
for(int j=1;j<=b[0];j++)
{
c[i+j-1]=a[i]*b[i]+c[i+j-1];//最开始的乘积
c[i+j]=c[i+j]+c[i+j-1]/10;//加上了进位
c[i+j-1]=c[i+j-1]%10;//这是在这一位上的数字
}
}
return;
}
part 5 除法运算
1.高精度数除以低精度数
- 注意除法是从高位开始的,所以这里输入的时候不用倒序存进数组啦会比较方便哦。
#include <bits/stdc++.h>
using namespace std;
char a[1000];
int b,c[1000],d,e,f[1000],h;//c是被除数,f是商,h是余数
void shuru()
{
cin>>a>>b;//b为除数
d=strlen(a);//d为位数
e=0;//为了防止输入的数字有前导0
if(a[e]=='0')
{
e++;
}
c[0]=d-e;//c[0]存位数
for(int i=e;i<=d;i++)
{
c[i-e+1]=a[i]-'0';//如果有前导0,那么e此时为1,也就是从a[1]算起;如果没有前导0,那么e=0,从a[0]算起
}
}
void chufa1()
{
int g=0;
f[0]=c[0];
for(int i=1;i<=c[0];i++)
{
g=g*10+c[i];
f[i]=g/b;
g=g%b;//得到余数
}
h=g;
}
void shuchu()
{
int i=1;
while(f[i]==0)//注意这里是while而不是if,因为可能前面几位都是0
{
i++;
}
while(i<=f[0])
{
cout<<f[i];
i++;
}
cout<<endl<<h<<endl;
return;
}
int main()
{
shuru();
chufa1();
shuchu();
return 0;
}
2.高精度数除以高精度数
具体每一步的步骤都在代码里,也有部分注释。我觉得最好用例子自己试试,看的还是很清楚哒!
#include <bits/stdc++.h>
using namespace std;
int a[1000],b[1000],c[1000];//a是被除数后来又用来存余数,b是除数,c是商
void shuru(int a1[])
{
char d[1000];
cin>>d;
a1[0]=strlen(d);
for(int i=1;i<=a1[0];i++)
{
a1[i]=d[a1[0]-i]-'0';//倒序存入数组
}
}
void yidong(int b1[],int e[],int wei)
{
for(int i=1;i<=b1[0];i++)
{
e[i+wei-1]=b1[i];//跟被除数的每一位对齐
}
e[0]=wei+b1[0]-1;//记录位数
}
int bijiao(int a1[],int b1[])//这里的1,-1,0都相当于标记,代表大小相等关系
{
if(a1[0]>b1[0])
return 1;
if(a1[0]<b1[0])
return -1;
for(int i=a1[0];i>0;i--)
{
if(a1[i]>b1[i])
return 1;
if(a1[i]<b1[i])
return -1;
}
return 0;
}
void jianfa(int a1[],int b1[])
{
int f;
f=bijiao(a1,b1);
if(f==0)//如果相等的情况
{
a1[0]=0;
return;
}
if(f==1)
{
for(int i=1;i<=a1[0];i++)
{
if(a1[i]<b1[i])
{
a1[i+1]--;//借位
a1[i]+=10;//注意哦,是加10
}
if(a1[i]>=b1[i])
{
a1[i]-=b1[i];
}
}
while((a1[a1[0]]==0)&&(a1[0]>0))
a[0]--;
return;
}
}
void chufa(int a1[],int b1[],int c1[])
{
int e[1000];
c1[0]=a1[0]-b1[0]+1;//确定商的最大位数
for(int i=c1[0];i>0;i--)//从最高位开始
{
memset(e,0,sizeof(e));//每次都清空
yidong(b1,e,i);
while(bijiao(a1,e)>=0)
{
c1[i]++;//得到商的每一位的数字
jianfa(a1,e);
}
}
while((c1[c1[0]]==0)&&(c1[0]>0))
{
c1[0]--;//确定商的位数
}
}
void shuchu(int a1[])
{
if(a1[0]==0)
{
cout<<"0"<<endl;
return;
}
for(int i=a1[0];i>0;i--)
cout<<a1[i];
cout<<endl;
return;
}
int main()
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
shuru(a);
shuru(b);
chufa(a,b,c);
shuchu(c);
shuchu(a);
return 0;
}