高精度算法
呦哄,又到了一个周末,各位小伙伴们赶紧端起手中的电脑吧,小编将和大家一起进行开(gao)心 ( jing ) 的 (du)玩 (suan)耍 (fa)的旅程。
例1、 高精度加法。
我们先来确定数据结构和基本算法:
1:接受原始数据:可用字符数组或字符串,s1[201],s2[201];
2:用来存放原始数据和结果的数组:a[201],b[201],c[201];以及与之对应的长度变量:lena,lenb,lenc;
3:用来储存进位的变量:x
算法流程:
1、 a,b,c数组清0,如果是全局可以省略。(循环或memset)
2、 读入s1,s2,并记下长度。
3、 将s1,s2中的数据倒序放入a,b数组,利用循环实现:
for (i=0;i<=lena-1;++i) a[lena-i]=s1[i]-48;
或:for (int i=1;i<=strlen(s1);++i) a[i]=s1[strlen(s1)-i]-‘0’;
4、 从低到高开始相加;用循环实现,结果放入c;中止条件为计算到a,b的最高位;
lenc=1;x=0;
while (lenc<=lena||lenc<=lenb)
{
c[lenc]=a[lenc]+b[lenc]+x; //相加,注意进位
x=c[lenc]/10; //计算进位
c[lenc]%=10; //计算本位
lenc++; //准备下一次计算
}
c[lenc]=x; //循环结束时,别忘记了最后的进位
5、输出,用for循环进行。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
char s1[201],s2[201];
int a[200],b[200],c[201],lena,lenb,lenc,i,x;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
gets(s1);gets(s2);
lena=strlen(s1);lenb=strlen(s2);
for (i=0;i<=lena-1;++i) a[lena-i]=s1[i]-48;
for (i=0;i<=lenb-1;++i) b[lenb-i]=s2[i]-48;
lenc=1;x=0;
while (lenc<=lena||lenc<=lenb)
{
c[lenc]=a[lenc]+b[lenc]+x;
x=c[lenc]/10;
c[lenc]%=10;
lenc++;
}
c[lenc]=x;
while (c[lenc]==0) lenc--; //消除最高位的0
for (i=lenc;i>=1;i--) cout<<c[i];
cout<<endl;
return 0;
}
例2、 高精度减法
提示:需要多考虑一个小数减大数的问题,并提前输出‘-’号;
减法要考虑借位,向被减数的高位借位。其他和加法大同小异。
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
char s1[201],s2[201],s3[201];
int a[200],b[200],c[201],lena,lenb,lenc,i,x;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
gets(s1);gets(s2);
if (strlen(s1)<strlen(s2)||(strlen(s1)==strlen(s2)&&strcmp(s1,s2)<0))
{
strcpy(s3,s1);strcpy(s1,s2);strcpy(s2,s3);cout<<'-';
}
lena=strlen(s1);lenb=strlen(s2);
for (i=0;i<=lena-1;++i) a[lena-i]=s1[i]-48;
for (i=0;i<=lenb-1;++i) b[lenb-i]=s2[i]-48;
i=1;
while (i<=lena)
{
if (a[i]<b[i]) //先判断是否需要借位
{
a[i]+=10;
a[i+1]--;
}
c[i]=a[i]-b[i];
++i;
}
lenc=i;
while (c[lenc]==0&&lenc>1) lenc--; //有可能出现结果为0
for (i=lenc;i>=1;--i) cout<<c[i];
cout<<endl;
return 0;
}
例3、 高精度乘法
数据结构:
char a1[1001],b1[1001]:原始数据接收
int a[300],b[300],c[410];乘数1,乘数2,积;
int lena,lenb,lenc,x;长度,进位;
算法流程:
1、 输入;
2、 字符数组的数据存入数组:
3、 用循环实行乘法运算:
for (i:1—lena) //i循环控制乘数
{
进位初始化为0;
for (j:1—lenb) //j控制被乘数
{c[i+j-1]=原位的数+当前积+进位; //特别要注意乘法和加法一起完成的
进位; //包括两个操作;
}
进位; //本轮循环的最后一个进位表示考虑;
}
4、输出。
整体代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
char s1[1001],s2[1001];
int a[1001],b[1001],c[2001],lena,lenb,lenc,i,j,x;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
gets(s1);gets(s2);
lena=strlen(s1);lenb=strlen(s2);
for (i=0;i<=lena-1;++i) a[lena-i]=s1[i]-48;
for (i=0;i<=lenb-1;++i) b[lenb-i]=s2[i]-48;
for (i=1;i<=lena;++i)
{
x=0;
for (j=1;j<=lenb;++j)
{
c[i+j-1]=a[i]*b[j]+c[i+j-1]+x; //当前积+原数+上次进位
x=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[i+lenb]=x; //最后的进位
}
lenc=lena+lenb;
while (c[lenc]==0&&lenc>1) --lenc;
for (i=lenc;i>=1;--i) cout<<c[i];
cout<<endl;
return 0;
}
例4、 上机练习,求10000以内的阶乘。
小伙伴们使用高精度算法求出10000以内的阶乘。
不会的同学请看下面的代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int a[10000];
int main()
{
int n,i,j,x,p;
cin>>n;
for (i=1;i<=10000;++i) a[i]=0;
a[1]=1;x=0;p=1;
for (i=1;i<=n;++i)
{
for (j=1;j<=p;++j)
{
a[j]=a[j]*i+x;
x=a[j]/10000; //每位数组元素存放四位整数
a[j]%=10000;
}
if (x!=0) {++p;a[p]=x;x=0;} //往前进位
}
cout<<a[p];
for (i=p-1;i>=1;--i) printf("%04d",a[i]); //中间项输出要补0
cout<<endl;
return 0;
}
例5: 高精度除以低精度
数据结构:
char a1[1001]:原始数据接收
int a[1000],c[1000];被除数,商;
int lena,lenc,x,b;长度,余数,除数;
算法流程:
1、 输入;
2、 字符数组的数据存入数组:
3、 按位相除,考虑可能出现的余数的处理。
4、 输出,记得消除前面的0;
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char a1[1000];
int a[1000],c[1000],x,b=13,i,lena,lenc;
int main()
{
gets(a1);
lena=strlen(a1);
for (i=0;i<=lena-1;++i) a[i+1]=a1[i]-48;
for (i=1;i<=lena;++i)
{
c[i]=(x*10+a[i])/b; //按位相除
x=(x*10+a[i])%b; //计算余数
}
lenc=1;
while (c[lenc]==0&&lenc<lena) lenc++; //删除前面的0
for (i=lenc;i<=lena;++i) cout<<c[i];
cout<<endl<<x<<endl; //输出余数
return 0;
}
好啦,本期的【高精度算法】课程就再次告一段落了,喜欢小编的博客的同学记得一定订阅小编的博客哟,好啦,我们下期再见!