对于A+B,如果A和B是有着1000个数位的整数,就不可以用基本的数据类型如int来存储了。这时只可以老实地模拟加减乘除的过程。大整数又称为高精度整数,其含义就是用基本数据类型无法存储其精度的整数。
我们可以用数组来存储大整数,比如用int型数组d[1000],这个数组的每一位就代表存放整数的每一位。数组的高下标存储的是整数的高位,低下标存储的是整数的低位。
为了方便获取大整数的长度,一般定义一个int型变量len来记录长度,并与d数组构成结构体。
struct bign
{
int d[1000];
int len;
};
最好在定义结构体之后马上对其进行初始化,防止后续忘记。可以在结构体中直接设置构造函数。
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
比较2个大整数的大小时,先比较2者的len,如果不相等,谁大谁的值就大。如果相等,从高位一次比较。
int compare(bign a,bign b)
{
if(a.len>b.len)
return 1;
else if(a.len=0;i--)
{
if(a.d[i]>b.d[i]) return 1;
else if(a.d[i]
(1)高精度加法(2)高精度减法 (3)高精度与低精度的乘法(4)高精度与低精度的除法
一般不会考虑高精度与高精度的乘除法。
回忆小学时期的加法
从低位开始。
7+5=12 保留个位数2,向高位进1
4+6=10,再加上进位的1为11,保留个位数1,向高位进1
1+0=1,再加上进位的1,为2。
因此每一位进行加法的步骤:将该位上2个数字和进位相加,取个位数作为该位结果,取十位数作为新的进位。
bign add(bign a,bign b) //高精度A+B
{
bign c;
int carry=0 //进位,初始位0;
for(int i=0;i
#include
#include
#include
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=0;i--)
{
printf("%d",a.d[i]);
}
}
int main()
{
char s1[100],s2[100];
scanf("%s%s",s1,s2);
bign a=change(s1);
bign b=change(s2);
print(add(a,b));
return 0;
}
这样的写法是2个非负整数 如果一方是负的,可以再转换到数组时去掉负号,采用高精度减法,如果都是负的,采用高精度加法,最后结果取负。
回忆小学时期的减法
依旧从低位开始
5-7 失败,从高位借1,4变为3,10+5-7=8
3-6失败,从高位借1,1变为0,10+3-6=7
0-0=0 (要特别注意:减法后高位可能存在0,要忽视,但又要保证至少有一位数)
bign sub(bign a,bign b)
{
bign c;
for(int i=0;i=1&&c.d[c.len-1]==0) //去除高位0,同时保证至少一位最低位
{
c.len--;
}
return c;
}
高精度乘法这里指bign类型与int类型的乘法,其与之前的乘法运算有点不同。以147*35为例,这里把147视为bign类型数据,35视为int类型。在求积中始终把35看作整体。
7*35=245 取个位数5作为该位结果,高位24作为进位
4*35=140,加上进位24,164 把个位数4作为该位结果,高位16作为进位。
1*35=35,加上进位16,得51,把个位数1作为该位结果,高位5作为进位。
没有数继续乘了,就把进位5直接作为结果的高位。(注意在没数可乘时,如果进位大于10,需要循环进位)
bign multi(bign a,int b)
{
bign c;
int carry=0; //进位
for(int i=0;i
首先说一下乘法计算的算法,从低位向高位乘,在竖式计算中,我们是将乘数第一位与被乘数的每一位相乘,记录结果,之后,用第二位相乘,记录结果并且左移一位,以此类推,直到计算完最后一位,再将各项结果相加,得出最后结果。
计算的过程基本上和小学生列竖式做乘法相同。为了编程方便,并不急于处理进位,而是将进位问题留待最后统一处理。
总结一个规律: 即一个数的第i 位和另一个数的第j 位相乘所得的数,一定是要累加到结果的第i+j 位上。这里i, j 都是从右往左,从0 开始数。
ans[i+j] = a[i]*b[j];
另外注意进位时要处理,当前的值加上进位的值再看本位数字是否又有进位;前导清零。
#include
#include
#include
#include
using namespace std;
int size_plus;
void multi(string &s1,string &s2,int c[])
{
int n=s1.size();
int m=s2.size();
int a[n];
int b[m];
int i,j;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(j=0,i=n-1;i>=0;i--)
{
a[j++]=s1[i]-'0';
}
for(j=0,i=m-1;i>=0;i--)
{
b[j++]=s2[i]-'0';
}
for(i=0;i>s1>>s2;
int size1=s1.size();
int size2=s2.size();
size_plus=size1+size2+5;
int res[size_plus];
memset(res,0,sizeof(res));
multi(s1,s2,res);
int i;
for(i=size_plus-1;i>=0;i--)
{
if(res[i]!=0)
break;
}
int len=i+1;
for(int j=len-1;j>=0;j--)
{
printf("%d",res[j]);
}
return 0;
}
除法运算与小学时的运算大致相同
1与7比较,不够除,商为0,余数为1
余数1和新位2组成12,12与7比较,够除,商为1,余数为5
余数5与新位3组合为53,53与7比较,够除,商为7,余数为4
余数4与新位4组合为44,44与7比较,够除,商为6,余数为2;
可以看出:上一步的余数乘以10加上该步的位,得到该步的临时被除数,将其与除数比较。若不够除,则商为0.要注意减法后高位可能会有多余的0,要忽视他们,但也要保证至少有一位数。
bign division(bign a,int b,int &r) //有的题目野火要求球的余数。
{
bign c;
c.len=a.len;
for(int i=a.len-1;i>=0;i--) //从高位开始
{
r=r*10+a.d[i];
if(r=1&&c.d[c.len-1]==0)
{
c.len--;
}
return c;
}
#include
#include
#include
struct bign
{
int d[1000];
int len;
bign()
{
memset(d,0,sizeof(d));
len=0;
}
};
bign change_to_bign(char str[])
{
bign a;
a.len=strlen(str);
for(int i=0;i=1&&c.d[c.len-1]==0)
{
c.len--;
}
return c;
}
bign multi(bign a,int b)
{
bign c;
int carry=0; //进位
for(int i=0;i=0;i--) //从高位开始
{
r=r*10+a.d[i];
if(r=1&&c.d[c.len-1]==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 s1[100],s2[100];
//模拟加法
printf("请输入要进行加法操作的2个数\n");
scanf("%s%s",s1,s2);
bign a=change_to_bign(s1);
bign b=change_to_bign(s2);
printf("%s+%s=",s1,s2);
print(add(a,b));
printf("\n");
//模拟减法
printf("请输入要进行减法操作的2个数\n");
scanf("%s%s",s1,s2);
a=change_to_bign(s1);
b=change_to_bign(s2);
printf("%s-%s=",s1,s2);
print(sub(a,b));
printf("\n");
//模拟乘法
printf("请输入要进行乘法操作的2个数\n");
scanf("%s%s",s1,s2);
bign f=change_to_bign(s1);
int d=change_to_int(s2);
printf("%s*%s=",s1,s2);
print(multi(f,d));
printf("\n");
//模拟除法
printf("请输入要进行除法操作的2个数\n");
int r=0;
scanf("%s%s",s1,s2);
a=change_to_bign(s1);
int e=change_to_int(s2);
printf("%s/%s=",s1,s2);
print(division(a,e,r));
printf(" %s%%%s=%d",s1,s2,r);
printf("\n");
}
给定两个数R和n,输出R的n次方,其中0.0 但是放到题目里边运行,总是提示我运行时间超时!可能是结构体很占用时间? 用字符串或数组表示大数,否则无法精确表示答案1的情况。同时注意2数相乘的位数。 函数BigDataMulti用于计算当前计算值(从数组尾到数组头为数字)与底数的乘积 高精度加减乘除推荐博客 #include
#include