大整数的四则运算

一  高精度加法

实现代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct bign ///big number 用一个结构体来表示一个大数
{
    int d[1000];///d为digit的缩写
    int len;
    bign(){///构造函数与结构体的名相同,竟然少写一个n,fuck,用来初始化结构体
        memset(d,0,sizeof(d));
        len=0;
    }
};
bign change(char str[])///字符型的大数转化为整型数组
{                     ///整数的高位存储在数组的高位
    bign a;           ///整数的低位存储在数组的低位
    a.len=strlen(str);
    for(int i=0;i<a.len;i++)
    {
        a.d[i]=str[a.len-1-i]-'0';
    }
    return a;
}
bign add(bign a,bign b)///大数相加
{
    bign c;
    int carry=0;///carry是进位
    for(int i=0;i<a.len||i<b.len;i++)///以较长的为界限
    {
        int temp=a.d[i]+b.d[i]+carry;///两个对应位与进位相加
        c.d[c.len++] =temp%10;///个位数为该位的结果
        carry=temp/10; ///十位数为新的进位
    }
    if(carry!=0)
      c.d[c.len++]=carry;
    return c;
}

void print(bign a)
{
    for(int i=a.len-1;i>=0;i--)
        printf("%d",a.d[i]);
        printf("\n");
}
int main()
{
    char str1[1000],str2[1000];///char数组二次赋值的时候不用初始化
       while(scanf("%s%s",str1,str2)!=EOF)
       {
           bign a=change(str1);
           bign b=change(str2);
           print(add(a,b));
       }

     return 0;
}



二 高精度减法

代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
struct bign
{
    int d[1000];
    int len;
    bign()
    {
        memset(d,0,sizeof(d));
        len=0;
    }
};
bign change(char str[])///输入的时候是高位在前,低位在后,要把它放过来
{                      ///存到数组中
    bign a;
    a.len=strlen(str);
    for(int i=0;i<a.len;i++)
    {
        a.d[i]=str[a.len-1-i]-'0';
    }
    return a;
}
bign sub(bign a,bign b)///高精度 A-B
{
    bign c;
    for(int i=0;i<a.len||i<b.len;i++)
    {
        if(a.d[i]<b.d[i])
        {
            a.d[i+1]--;
            a.d[i]+=10;
        }
        c.d[c.len++]=a.d[i]-b.d[i];
    }
    while(c.len-1>=1&&c.d[c.len-1]==0)///减法后高位可能有多余的 0
    {                       ///要忽视它们,但也要保证结果至少有一位数
        c.len--;
    }
    return c;
}
void print(bign a)///输出的时候先输出最高位
{
    for(int i=a.len-1;i>=0;i--)
        printf("%d",a.d[i]);
}
int main()
{
    char str1[1000],str2[1000];
    scanf("%s%s",str1,str2);
    bign a=change(str1);
    bign b=change(str2);
    print(sub(a,b));
}



三 高精度与低精度的乘法

所谓的低精度就是可以用基本的数据类型存储的数据,例如 int 型。这里讲述的就是 bign 与 int 类型的乘法。以 147*35 为例,这里把147 是为 bign 类型,35视为 int 类型,在计算的过程中,始终将 35 作为一个整体来看待。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct bign///结构体表示一个高精度的大数
{
    int d[1000];
    int len;
    bign()
    {
        memset(d,0,sizeof(d));
        len=0;
    }
};
bign change(char str[])
{
    bign a;
    a.len=strlen(str);
    for(int i=0;i<a.len;i++)
    {
        a.d[i]=str[a.len-i-1]-'0';
    }
    return a;
}
bign multi(bign a,int b)
{
    bign c;
    int carry=0;
    for(int i=0;i<a.len;i++)
    {
        int temp=a.d[i]*b+carry;
        c.d[c.len++]=temp%10; ///个位作为该位的结果
        carry=temp/10;  ///高位部分作为新的进位
    }
    while(carry!=0)///和加法不一样,乘法的进位可能不止一位ieee,因此用while
    {
        c.d[c.len++]=carry%10;
        carry/=10;
    }
    return c;
}
void print(bign a)
{
    for(int i=a.len-1;i>=0;i--)
    {
        printf("%d",a.d[i]);
    }
}
int main()
{
    char str[1000];
    int a;
    scanf("%s%d",str,&a);///握草,竟然忘了加赋值号
    bign x=change(str);
    print(multi(x,a));
    return 0;
}



四 高精度与低精度的除法

除法的计算和小学所学的是相同的。

步骤:上一步的余数乘以 10 加上该步的位,得到该步临时的被除数,将其与除数比较:如果不够除,则该位的商为 0 ;如果够除 ,则商即为对应的商,余数即为对应的余数。

最后一步要注意高位可能有多余的 0,要忽视它们,但也要保证结果至少有一位数。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct bign
{
    int d[1000];
    int len;
    bign()
    {
        memset(d,0,sizeof(d));
        len=0;
    }
};
bign change(char str[])
{
    bign a;
    a.len=strlen(str);
    for(int i=0;i<a.len;i++)
    {
        a.d[i]=str[a.len-i-1]-'0';
    }
    return a;
}
bign divide(bign a,int b,int &r)///高精度的除法,r为余数
{
    bign c;
    c.len=a.len;///被除数的每一位和商的每一位都是一一对应的,因此先令长度相等
    for(int i=a.len-1;i>=0;i--)
    {
       r=r*10+a.d[i];
       if(r<b) c.d[i]=0;///不够除,该位为0
       else    /// 够除
       {
           c.d[i]=r/b; ///商
           r=r%b;    ///获得新的余数
       }
    }
    while(c.len-1>=1&&c.d[c.len-1]==0)///高位可能有多余的 0,要忽视它们
    {
        c.len--;
    }
    return c;
}
void print(bign a)
{
    for(int i=a.len-1;i>=0;i--)
        printf("%d",a.d[i]);
        printf("\n");
}
int main()
{
    char str[1000];
    int a,r=0;
    scanf("%s%d",str,&a);
    bign x=change(str);
    print(divide(x,a,r));
    printf("%d",r);
}

五 高精度与高精度的乘法

一位位地运算,

我们再声明一个数组c来储存答案。大家通过一个简单的乘法运算进行模拟就可以看出,
以同样的储存规则,a[0] * b[0] = c[0]; a[0] * b[1] + a[1] * b[0] = c[1];
逐渐我们可以发现规律: "c[i + j] += a[i] * b[j]"同过一个循环去实现,就可以把c[i + j]计算出来,为什么呢,因为a[i]=x*10^i, a[j]=y*10^j; a[i]*a[j]=x*y*10^(i+j); i , j表示的为数组的下标
需要指出的是,这里的计算我们还没有进行进位处理。

代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct bign
{
    int d[1000];
    int len;
    bign()
    {
        memset(d,0,sizeof(d));
        len=0;
    }
};
bign change(char str[])
{
    bign a;
    a.len=strlen(str);
    for(int i=0;i<a.len;i++)
    {
        a.d[i]=str[a.len-1-i]-'0';
    }
    return a;
}
bign multi(bign a,bign b)///高精度与高精度相乘
{
    bign c;
    for(int i=0;i<a.len;i++)///
    {
        for(int j=0;j<b.len;j++)
            c.d[i+j]+=a.d[i]*b.d[j];
    }
    
    c.len=a.len+b.len;///得到c的位数的个数
    
    for(int i=0;i<c.len;i++)///处理进位
        if(c.d[i]>10)
    {
        c.d[i+1]+=c.d[i]/10;
        c.d[i]%=10;
    }
    while(c.len-1>=1&&c.d[c.len-1]==0)///除去高位为 0 的
    {
        c.len--;
    }
    return c;
}
void print(bign a)
{
    for(int i=a.len-1;i>=0;i--)
        printf("%d",a.d[i]);
        printf("\n");
}
int main()
{
        char str1[1000],str2[1000];
        scanf("%s%s",str1,str2);
        bign a=change(str1);
        bign b=change(str2);
        print(multi(a,b));
      return 0;
}

六 高精度除法


 持续更新中,暂时还找不到特别优化的算法



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值