CHAPTER_5 数学问题入门
5.6.1大整数的存储
大整数又称高精度整数,其含义是用基本数据类型无法存储其精度的整数。 例如一个有1000个数位的整数,我们无法用基本数据类型来存储这个数。
我们使用一个数组来存储大整数。例如定义一个int型数组d[1000],将整数235813存入,即有d[0]=3,d[1]=1,d[2]=8,d[3]=5,d[4]=3,d[5]=2。即整数的高位存储在数组的高位,整数的地位存储在数组的低位。需要注意的是,把整数按字符串%s读入时需要反转再存入数组d[]。
大整数存储结构定义如下:
typedef struct {
int d[1000];
int len; //d[]数组存放整数,len记录长度
bign() {
memset(d,0,sizeof(d));
len=0;
} // 自定义构造函数,用于自动初始化结构体变量
}bign;
我们在输入大整数时,首先用字符串读入,然后将其翻转存入bign结构体中
bign change(string str) { //将输入字符串存入结构体中
bign a;
a.len=str.length(); //赋值整数的长度
reverse(str.begin(),str.end()); //reverse()函数位于algorithm头文件,用于反转
for(int i=0;i<a.len;i++) {
a.d[i]=str[i]-'0';
} //为d[]依次赋值
return a;
}
解决了存储和输入问题后,我们怎么比较两个大整数的大小呢?
规则很简单:先判断两者的bign.len的大小,如果不相等,则len大的bign大;如果相等,遍历两者的d[1000]从高位到地位进行比较,直到出现某一位不等,就可以判断两者大小。
5.6.2大整数的四则运算
我们主要介绍四种大整数运算:高精度加法、高精度减法、高精度乘低精度、高精度除以低精度。 至于高精度与高精度的乘除,一般考试不会涉及,故不在此赘述。
高精度加法
加法原理很简单 ,我们对某一位进行相加,得出的数字中,个位数作为该位结果,十位数作为下一位的进位。我们可以得到代码如下:
bign add(bign a,bign b) {
bign c;
int tmp=0; //临时变量,用来存储进位
for(int i=0;i<a.len||i<b.len;i++) {
int sum=a.d[i]+b.d[i]+tmp;
c.d[i]=sum%10; //两个数的对应位相加,再加上进位,余10取出个位
c.len++;
tmp=sum/10; //十位取出,赋予tmp
}
if(tmp) { //如果最后进位不为0,说明结果数比原来两个数位数更高
c.d[c.len]=tmp; //例如55+60=115,将多余的进位赋予c
c.len++;
}
return c;
}
高精度减法
减法的步骤也很容易,我们先假设被减数a大于减数b。对某一步,比较被减位和减位,如果不够减,则令高位减1被减位加10,再进行减法;如果够减,则直接减。
bign minu(bign a,bign 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[i]=a.d[i]-b.d[i];
c.len++; //将结果赋予c
}
while(c.d[len-1]==0&&c.len!=1) {
c.len--;
} //去除高位的0,例如2233-2211=0022,将开头的两个0去除
return c;
}
PS:在上面的讨论中我们已经解决了高精度之间的加减。但是还有两个小问题要注意。
(1)加法时如果两个数为负数,我们将负号去除,再按照上面算法做加法,最后结果再加负号。
(2)上面的减法过程中,默认减数大于被减数。我们将减数和被减数互换,按照上面算法做减法,最后结果再加负号。
高精度乘低精度
低精度就是可以用基本类型存储的数据,例如int型。乘法过程稍比加法复杂,我们以147*35为例。(假设147为bign类型,35为int型)

因此对于某一步:取bign的某位与int数相乘,再与进位相加,所得个位数为当位结果,高位部分作为进位。
bign multi(bign a,int n) {
bign c;
int tmp=0; //tmp存储进位
for(int i=0;i<a.len;i++) {
int sum=a.d[i]*n+tmp;
c.d[i]=sum%10;
c.len++;
tmp=sum/10;
}
while(tmp) { //与加法不同,乘法进位可能不止一位数,因此要循环处理
c.d[c.len-1]=tmp%10;
c.len++;
tmp/=10;
}
return c;
}
高精度除以低精度
我们以1234/7为例。(假设1234为bign类型,7为int型)

因此对于某一步:上一步的余数乘以10加上该步的位,得到该步临时的被除数,将其与除数比较:如果不够除,则该位商为0;如果够除,则商为对应的商,余数即为对应的余数。
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;
else {
c.d[i]=r/b;
r=r%b;
}
}
while(c.d[len-1]==0&&c.len!=1) { //和减法相同,去除高位0
c.len--;
}
return c;
}
本文介绍了大整数(高精度整数)的存储方式,通过数组存储并利用结构体记录长度。详细讲解了大整数的加法、减法操作,以及如何将大整数与低精度整数进行乘法和除法运算。在加法中,使用逐位相加和进位的概念;在减法中,处理了不够减的情况;乘法涉及逐位相乘与进位;除法则通过不断求余和比较来实现。此外,还讨论了负数的处理和结果的规范化。
226

被折叠的 条评论
为什么被折叠?



