高精
高精
高精度计算中需要处理好以下几个问题:
(1)数据的接收方法和存贮方法
数据的接收和存贮:当输入的数很长时,可采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。另一种方法是直接用循环加数组方法输入数据。
void init(int a[]) //传入一个数组
{
string s;
cin>>s; //读入字符串s
a[0]=s.length(); //用a[0]计算字符串s的位数
for(i=1;i<=a[0];i++)
a[i]=s[a[0]-i]-'0'; //将数串s转换为数组a,并倒序存储
}另一种方法是直接用循环加数组方法输入数据。
(2) 高精度数位数的确定
位数的确定:接收时往往是用字符串的,所以它的位数就等于字符串的长度。
(3) 进位,借位处理
加法进位:c[i]=a[i]+b[i];
if (c[i]>=10) { c[i]%=10; ++c[i+1]; }
减法借位:if (a[i]<b[i]) { --a[i+1]; a[i]+=10; }
c[i]=a[i]-b[i];
乘法进位:c[i+j-1]= a[i]*b[j] + x + c[i+j-1];
x = c[i+j-1]/10;
c[i+j-1] %= 10;
(4) 商和余数的求法
商和余数处理:视被除数和除数的位数情况进行处理.
第一节 高精加。
【分析】竖式加法
因此,算法描述如下:
int c[100];
void add(int a[],int b[]) //a,b,c都为数组,分别存储被加数、加数、结果
{
int i=1,x=0; //x是进位
while ((i<=a数组长度)||(i<=b数组的长度))
{
c[i]=a[i]+b[i]+x; //第i位相加并加上次的进位
x=c[i]/10; //向高位进位
c[i]%=10; //存储第i位的值
i++; //位置下标变量
}
}
第二节 高精减
【算法分析】竖式减法
类似加法,可以用竖式减法。在做减法运算时,需要注意的是:被减数必须比减数大,同时需要处理借位。高精度减法的参考程序:
cin>>st1>>st2;
int len1=st1.size(),len2=st2.size(),i;
FORa(i,1,len1) a[i]=st1[len1-i]-'0';
FORa(i,1,len2) b[i]=st2[len2-i]-'0';
FORa(i,1,len1)
{
a[i]=a[i]-b[i];
if(a[i]<0) a[i]+=10,a[i+1]--;借位
}
while(!a[len1]&&len1>1)
len1--;处理前导零
FORs(i,len1,1) cout<<a[i];
第三节 高精乘
len=len1+len2+2;
FORa(i,1,len1)
{
int x=0;
FORa(j,1,len2)
{
c[i+j-1]+=a[i]*b[j]+x; 进位
x=c[i+j-1]/10;
c[i+j-1]%=10;
}
if(x)
c[i+len2]=x;
}
while(!c[len]&&len>1)
len--; 前导零
第四节 低精除
FORa(i,1,len1)
{
s=s*10+a[i];
if(s>b) break;寻找商一
}
c[++tot]=s/b,s%=b;
FORa(i,i+1,len1)
{
s=s*10+a[i];
c[++tot]=s/b;储存商
s%=b;
}余数即为最后的s
【总结】:
- 乘法,减法的进位,借位,前导零
- 压位高精的第一位特殊处理,每一个单位的进位原则,注意:需要现将每一位乘上乘数,最后再考虑动态进位
- 高精减需要考虑最后一位,即只能len>1的时候,len才能减
感谢各位与信奥一本通的鼎力相助!