您的位置:首页 > 其它

大整数的四则运算

2017-08-18 09:58 260 查看
一  高精度加法
实现代码:
#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;
}


六 高精度除法

 持续更新中,暂时还找不到特别优化的算法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐