(C++)高精度整数的存储读入比较和四则运算

Posted CSU迦叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(C++)高精度整数的存储读入比较和四则运算相关的知识,希望对你有一定的参考价值。

目录

1. 存储

2. 读入

3. 比较大小

4. 加法

5. 减法

6. 高精度整数和低精度整数的乘法

7. 高精度整数除以低精度整数


高精度整数,又称大整数,其含义就是用基本数据类型无法存储其精度的整数。如:10进制下有着1000个数位的整数。

低精度整数,就是可以用基本数据类型存储的整数。

1. 存储

采用整型数组顺位存储,即整数高位存储在数组高位。为了方便随时获取长度,因此定一个int len和int []组成结构体bign(取自big number)。

同时在结构体中使用构造函数,进行初始化。

struct bign{
	int d[1000];
	int len;
	
	bign(){
		memset(d,0,sizeof(d));
		len = 0;
	}
};

2. 读入

作为字符串读入,再把字符串另存至bign结构体。

由于是顺位存储,因此字符串要逆着输进结构体数组,同时记得 -‘0’ 将字符转化为整数

下面是将字符串转化为bign结构体的函数

bign change(char s[]){
	bign bg;
	bg.len = strlen(s);
	for(int i=0;i<bg.len;i++){
		bg.d[i] = s[bg.len-1-i] - '0';
	}
	
	return bg;
}

3. 比较大小

原理:先比较两个大整数的长度,更大的直接胜出;从高位到低位逐位比较大小,直至出现某一位不相等,那一位上更大胜出。

结果为int型,如果第一个大于第二个,返回1,等于返回0,小于返回-1。

int compare(bign a,bign b){
	if(a.len>b.len)return 1;
	else if(a.len<b.len)return -1;
	else{
		for(int i=a.len-1;i>=0;i--){
			if(a.d[i]>b.d[i])return 1;
			else if(a.d[i]<b.d[i])return -1;
		}
		return 0;
	}
}

4. 加法

原理:从低位到高位逐位相加,每一个和的个位保留在原位,十位进到更高位。

c = a + b (a>=0,b>=0 )

注意:遍历的过程中位数取a和b中位数更多的那个,结果可能超过a和b的长度。

bign add(bign a,bign b){
	bign c;
	int carry = 0;//进位 
	int sum;
	for(int i=0;i<a.len||i<b.len;i++){
		sum = a.d[i] + b.d[i] + carry;
		c.d[c.len++] = sum%10;
		carry = sum/10;
	}
	//对于高于a和b的那个位数是否有数字取决于进位的最后值
	if(carry)c.d[c.len++] = carry;	
	return c; 	
}

注意,这里的加法只适用于两者都是非负的。如果有一个是负的,应该采用高精度减法,如果两个都是负的,就先转化成正的相加最后加上负号。 

5. 减法

原理:从低位到高位逐位相减,不够的向上一位借。最后对结果的长度进行纠正,从最高位开始,如果那一位上的数字是0,那么长度减一,但是长度不会为0至少为1。

不用担心向高位借但是高位也是0,因为短暂变成-1之后在下一轮比较时会向更高位借。

c = a - b (a>=b>=0)

bign sub(bign a,bign b){
	bign c;
	for(int i;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.d[c.len-1]==0&&c.len>1){//矫正位数,高位是0就长度减1,但是长度至少为1 
		c.len --;
	}
}

注意:这里要求被减数不小于减数,如果不满足要求,需要先把两个数进行交换。 

6. 高精度整数和低精度整数的乘法

得到的自然是高精度整数。

原理:bign从低位开始逐位和int的整体相乘,得到的结果个位保留在本位,其余高位(不是十位)进到下一步运算。

bign c = bign a * int b

bign multi(bign a,int b){
	bign c;
	int carry = 0;
	int product;//乘积
	for(int i;i<a.len;i++){
		product = a.d[i]*b + carry;
		c.d[c.len++] = product%10;
		carry = product/10;
	}
	
	while(carry){//注意此处和加法的区别 
		c.d[len++] = carry % 10;
		carry /= 10;
	} 
	
	return c;
}

7. 高精度整数除以低精度整数

得到的是高精度整数(低精度实际上可以视为高精度的子集)。

原理:bign从高位到低位逐位对int进行除操作,除之前余数*10加上当前位(开始把余数写成引用“引用”的形式传入是为了直接对原变量进行修改,最后得到的余数也就是结果),如果不够除(当前位已经被加到余数中),则当前位记为0,够除则将除得的商留在当前为,除得的余数用来更新余数。

(a + r)/b = c 余数r(存到传进的作为余数的变量r)

bign divide(bign a,int b,int& r){//调用的时候r是int类型的
	bign c;
	c.len = a.len;
	for(int i = c.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[c.len-1]==0&&c.len>1){//矫正位数,高位是0就长度减1,但是长度至少为1 
		c.len --;
	}
	
	return c; 
}

summary:

加和乘最后需要根据进位有无增加长度(新增位上当然要有数值)

减和除最后需要根据高位有无减少长度(但是边界是长度至少为1)

以上是关于(C++)高精度整数的存储读入比较和四则运算的主要内容,如果未能解决你的问题,请参考以下文章

高精度运算 Java算法

高精度计算

『模板 高精度计算』

任意精度无符号整数仅支持后增量运算符

C++不知算法系列之高精度数值的处理算法

初涉算法——大整数类