高精度算法

高精度算法

呦哄,又到了一个周末,各位小伙伴们赶紧端起手中的电脑吧,小编将和大家一起进行开(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循环控制乘数
{
进位初始化为0for (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;
}

好啦,本期的【高精度算法】课程就再次告一段落了,喜欢小编的博客的同学记得一定订阅小编的博客哟,好啦,我们下期再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值