高精度计算
计算机数据范围的表示有一定限制,如整型int、实数型double只能提供十几位的有效数字,如果计算位数超过100位,甚至1000位怎么办?这类问题通常采用高精度计算的方法解决。
高精度计算可以是整数间的计算,也可以是实数间的计算,其中实数间的高精度计算较为复杂。
初次写高精度计算多试错、调试几次应该都能写出来,但我们应该最终熟悉、掌握一种思路清晰、简洁正确的高精度计算写法。下面介绍一种较好的整数高精度计算写法。
读入高精度数
一般借助字符串读入高精度数,再将每位数字分别储存在数组中。高精度的第一位存储个位,而字符串的第一位存储最高位,所以需要进行逆序存储。通常情况下,会在数组的0号下标存储高精度数的位数以便输出。
void read(int a[])
{
memset(a,0,sizeof(a));//清0
string s;
cin>>s;
int l=s.length();
for(int i=1;i<=l;i++)
a[i]=s[l-i]-'0';
a[0]=l;
}
高精度加法
void add(int a[],int b[],int c[])
{
memset(c,0,sizeof(c));
int w=max(a[0],b[0])+1;
int z=0; //z是进位
for(int i=1;i<=w;i++)
{
c[i]=a[i]+b[i]+z;
z=c[i]/10;
c[i]%=10;
}
while(a[w]==0)w--;
c[0]=w;
for(int i=c[0];i>0;i--)cout<<c[i];//输出结果,根据实际可忽略
}
高精度减法
int compare(int a[],int b[])
{
int w=max(a[0],b[0]);
while(a[w]==b[w]&&w>0)w--;
if(w==0)return 0;
if(a[w]>b[w])return 1;
else return -1;
}
void sub(int a[],int b[],int c[])
{
memset(c,0,sizeof(c));
int w=a[0];
int z=0; //z为退位
for(int i=1;i<=w;i++)
{
c[i]=a[i]-b[i]-z;
if(c[i]<0)
{
c[i]+=10;
z=1;
}
else
z=0;
}
while(a[w]==0&&w>1)w--;
c[0]=w;
for(int i=c[0];i>0;i--)cout<<c[i];//输出结果,根据实际可忽略
}
int main()
{
...
int x=compare(a,b);//保证大数减小数
if(x==0)cout<<0;
else if(x==1)sub(a,b,c);
else
{
cout<<'-';
sub(b,a,c);
}
...
}
高精度乘法
void mul(int a[],int b[],int c[])
{
memset(c,0,sizeof(c));
for(int i=1;i<=a[0];i++)
for(int j=1;j<=b[0];j++)
{
c[i+j-1]=a[i]*b[j];
c[i+j]+=c[i+j-1]/10; //进位
c[i+j-1]%=10;
}
int w=a[0]+b[0];
while(c[w]==0&&w>1)w--;
c[0]=w;
for(int i=c[0];i>0;i--)cout<<c[i];//输出结果,根据实际可忽略
}
高精度数除法
这里主要讨论高精度数除以低精度数
void div(int a[],int b,int c[])
{
memset(c,0,sizeof(c));
int w=a[0];
int z=0; //余数
for(int i=w;i>0;i--)
{
c[i]=(a[i]+z*10)/b;
z=(a[i]+z*10)%b;
}
while(c[w]==0&&w>1)w--;
c[0]=w;
for(int i=c[0];i>0;i--)cout<<c[i];//输出结果,根据实际可忽略
}
看两道题
这道题直接套用上面高精度加法解决。
稍微综合了一下几种高精度计算,注意运用求和公式。
#include <bits/stdc++.h>
using namespace std;
int a[105],b[105],c[300],d[300];
void read(int a[])
{
int len,i;
string s;
cin>>s;
len=s.length();
memset(a,0,sizeof(a));
for(int i=1;i<=len;i++)
a[i]=s[len-i]-'0';
a[0]=len;
}
void add(int a[],int b[])
{
memset(b,0,sizeof(b));
int x=1;
int w=a[0]+1;
for(int i=1;i<=w;i++)
{
b[i]=a[i]+x;
x=b[i]/10;
b[i]%=10;
}
int i=104;
while(b[i]==0) i--;
b[0]=i;
}
void mul(int a[],int b[],int c[])
{
memset(c,0,sizeof(c));
for(int i=1;i<=a[0];i++)
{
for(int j=1;j<=b[0];j++)
{
c[i+j-1]+=a[i]*b[j];
int x=c[i+j-1]/10;
c[i+j-1]%=10;
c[i+j]+=x;
}
}
int i=a[0]+b[0];
while(c[i]==0&&i>0) i--;
c[0]=max(1,i);
}
void div(int c[],int d[])
{
int x=0;
memset(d,0,sizeof(d));
for(int i=c[0];i>0;i--)
{
x=x*10+c[i];
d[i]=x/2;
x%=2;
}
int i=c[0];
while(d[i]==0&&i>0) i--;
d[0]=max(i,1);
for(int i=d[0];i>0;i--) cout<<d[i];
}
int main()
{
read(a);
add(a,b);
mul(a,b,c);
div(c,d);
return 0;
}