C++类实现大整数

概要

在计算机科学和工程中,整数类型有一个上限,称为其最大值或最大表示值,这限制了数字的大小范围。在一些应用中,需要处理比这个上限更大的整数,这时就需要使用大整数类。

大整数类允许处理比计算机所提供的整数类型更大的整数,通常是以字符串形式存储,可以进行算术运算、比较和转换等操作。这在密码学、数值计算、物理仿真、金融等领域中非常有用。

比如在密码学中,RSA加密算法就需要对非常大的整数进行加密和解密。在数值计算中,需要进行高精度计算,避免舍入误差,保证计算结果的准确性。在物理仿真中,需要模拟非常大或非常小的量。在金融领域中,需要处理非常大的金额或精确的计算结果。

因此,大整数类是一个非常有用的工具,可以扩展计算机的数字处理能力,解决很多实际问题。

然而,C++并没有自己的大整数类,因此便想要自己实现一个头文件,方便一般高精度计算的使用。

备注

这里实现的大整数类只有逻辑运算和+-*/基本操作,以及重载输入输出,并且无法输入负数,只有在实现减法时,可以输出负数。因此有一定的局限性,有时间的话我会将取模,幂运算,自增,自减等加上去的!

具体实现

1.定义大整型类

用数组模拟大数,读入使用字符串,并且倒序放置

即  123456-->654321 进行存放,1记为第一位

typedef class BigInt {
	private:
		int num[MAXN];
		int len;
		bool sign;
	public:
		static int max_Big(int x, int y) {
			return x > y ? x : y;
		}
		BigInt(int x) { //初始化使得大整型能够表示整型
			memset(num, 0, sizeof(num));
			for (len = 1; x; len++) {
				num[len] = x % 10;
				x /= 10;
			}
			sign = 1;
			len--;//由于上述循环中len多加了一次,因此这里减去
		}
		BigInt() {
			memset(num, 0, sizeof(num));
			len = 0;
			sign = 1;
		}
		BigInt(std::string s) {
			len = s.length();
			int cnt = len - 1;
			for (int i = 1; i <= len; i++) {
				num[i] = s[cnt--] - '0';
			}
			sign = 1;
		}
		BigInt(char *s) {
			len = strlen(s);
			int cnt = 1;
			for (int i = len - 1; i >= 0; i--) num[cnt++] = s[i] - '0';
		}
		void flatten(int L) { //进行展平操作
			len = L;
			for (int i = 1; i <= len; i++) {
				num[i + 1] += num[i] / 10;
				num[i] %= 10;
			}
			while (!num[len]) { //删除多余位数
				len--;
			}
		}
		friend std::ostream& operator<<(std::ostream&iout, BigInt&I1);
		friend std::istream& operator>>(std::istream&iint, BigInt&I1);
		BigInt& operator = (const BigInt &I) {  //重载赋值运算符
			len = I.len;
			sign=I.sign;
			memset(num, 0, sizeof(num));
			for (int i = 1; i <=len; i++)
				num[i] = I.num[i];
			return *this;
		}
		friend BigInt operator+(BigInt&I1, BigInt&I2);
		friend BigInt operator-(BigInt&I1, BigInt&I2);
		friend BigInt operator*(BigInt&I1, BigInt&I2);
		friend BigInt operator/(BigInt I1, BigInt&I2);//大整型除以大整型-减法模拟除法
		friend BigInt operator/(BigInt&I1, int I2);//大整型除以整型-逐位试商法
		friend bool operator<(const BigInt&I1, const BigInt&I2);
		friend bool operator>(const BigInt&I1, const BigInt&I2);
		friend bool operator!=(const BigInt&I1, const BigInt&I2);
		friend bool operator==(const BigInt&I1, const BigInt&I2);
		friend bool operator<=(const BigInt&I1, const BigInt&I2);
		friend bool operator>=(const BigInt&I1, const BigInt&I2);
} BigInt;

2.算数运算符重载

Ⅰ.加法重载

将每一位的数加起来,最后一次性铺平即可

BigInt operator+(BigInt&I1, BigInt&I2) {
	int L = BigInt::max_Big(I1.len, I2.len) + 1;
	BigInt I3;
	for (int i = 1; i <= L; i++) {
		I3.num[i] = I1.num[i] + I2.num[i];
	}
	I3.flatten(L);
	return I3;
}

 以下是铺平操作的代码

void flatten(int L) { //进行展平操作
			len = L;
			for (int i = 1; i <= len; i++) {
				num[i + 1] += num[i] / 10;
				num[i] %= 10;
			}
			while (!num[len]) { //删除多余位数
				len--;
			}
		}
Ⅱ.减法重载

如果减数大于被减数,则倒置,即让减数减去被减数,最后在结果前加一个符号即可。

利用我们小学学习的知识:减法的竖式计算,向前一位借一位进行计算。

BigInt operator-(BigInt&I1, BigInt&I2) {
	int L = BigInt::max_Big(I1.len, I2.len);
	BigInt i1, i2, I3;
	if (I1 < I2) {
		i1 = I2;
		i2 = I1;
		I3.sign = 0;
	} else {
		i1 = I1;
		i2 = I2;
		I3.sign = 1;
	}
	for (int i = 1; i <= L; i++) {
		if (i1.num[i] < i2.num[i]) {
			i1.num[i + 1]--;
			i1.num[i] += 10;
		}
		I3.num[i] = i1.num[i] - i2.num[i];
	}
	while (I3.num[L] == 0 && L > 1) L--;
	I3.len = L;
	return I3;
}
Ⅲ.乘法重载

第一个数的第i位×第二个数的第j位的贡献在结果的第i+j-1的位置上。

完成后,将结果数铺平即可。

BigInt operator*(BigInt&I1, BigInt&I2) {
	BigInt I3;
	int len1 = I1.len, len2 = I2.len;
	int L = len1 + len2;
	for (int i = 1; i <= len1; i++)
		for (int j = 1; j <= len2; j++) {
			I3.num[i + j - 1] += I1.num[i] * I2.num[j];
		}
	I3.flatten(L);
	return I3;
}
Ⅳ.除法重载 

 ①大数/小数

使用逐位试商法进行计算,类似于除法的竖式计算

BigInt operator/(BigInt&I1, int I2) {
	BigInt I3;
	int x = 0;
	int len = I1.len;
	for (int i = len; i >= 1; i--) {
		I3.num[i] = (x * 10 + I1.num[i]) / I2;
		x = ((x * 10 + I1.num[i])) % I2;
	}
	I3.flatten(len);
	return I3;
}

②大数/大数

使用减法模拟除法 

 

BigInt operator/(BigInt I1, BigInt&I2) {
	BigInt I3;
	int len1 = I1.len, len2 = I2.len;
	int start = len1 - len2 + 1;
	for (int i = start; i >= 1; i--) {
		BigInt tmp1, tmp2(10);
		tmp1 = I2;
		while (tmp1.len < i) {
			tmp1 = tmp1 * tmp2;
		}
		while (I1 >= tmp1) {
			I3.num[i]++;
			I1 = I1 - tmp1;
		}
	}
	I3.flatten(start);
	return I3;
}

 3.赋值运算符,输入输出运算符重载

Ⅰ.赋值运算符重载
BigInt& operator = (const BigInt &I) {  //重载赋值运算符
			len = I.len;
			sign=I.sign;
			memset(num, 0, sizeof(num));
			for (int i = 1; i <=len; i++)
				num[i] = I.num[i];
			return *this;
		}

要注意的是,该赋值运算符在类内定义 

Ⅱ.输入输出运算符重载
std::istream& operator>>(std::istream&iint, BigInt&I1) { //重载输入
	std::string s;
	iint >> s;
	I1.len = s.length();
	int cnt = I1.len - 1;
	for (int i = 1; i <= I1.len; i++) {
		I1.num[i] = s[cnt--] - '0';
	}
	return iint;
}
std::ostream& operator<<(std::ostream&iout, BigInt &I1) { //重载输出
	if (!I1.sign) std::cout<< '-';
	for (int i = BigInt::max_Big(I1.len, 1); i >= 1; i--) {
		iout << I1.num[i];
	}
	return iout;
}

 4.逻辑运算符重载

bool operator<(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 < len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] < I2.num[i];
	}
	return false;
}
bool operator<=(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 < len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] < I2.num[i];
	}
	return true;
}
bool operator>(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 > len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] > I2.num[i];
	}
	return false;
}
bool operator>=(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 > len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] > I2.num[i];
	}
	return true;
}
bool operator==(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return false;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return false;
	}
	return true;
}
bool operator!=(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return true;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return true;
	}
	return false;
}

完整代码

#ifndef BIGINT_H
#define BIGINT_H
#define MAXN 100000
#include <string.h>
#include <iostream>
#include <string>
typedef class BigInt {
	private:
		int num[MAXN];
		int len;
		bool sign;
	public:
		static int max_Big(int x, int y) {
			return x > y ? x : y;
		}
		BigInt(int x) { //初始化使得大整型能够表示整型
			memset(num, 0, sizeof(num));
			for (len = 1; x; len++) {
				num[len] = x % 10;
				x /= 10;
			}
			sign = 1;
			len--;//由于上述循环中len多加了一次,因此这里减去
		}
		BigInt() {
			memset(num, 0, sizeof(num));
			len = 0;
			sign = 1;
		}
		BigInt(std::string s) {
			len = s.length();
			int cnt = len - 1;
			for (int i = 1; i <= len; i++) {
				num[i] = s[cnt--] - '0';
			}
			sign = 1;
		}
		BigInt(char *s) {
			len = strlen(s);
			int cnt = 1;
			for (int i = len - 1; i >= 0; i--) num[cnt++] = s[i] - '0';
		}
		void flatten(int L) { //进行展平操作
			len = L;
			for (int i = 1; i <= len; i++) {
				num[i + 1] += num[i] / 10;
				num[i] %= 10;
			}
			while (!num[len]) { //删除多余位数
				len--;
			}
		}
		friend std::ostream& operator<<(std::ostream&iout, BigInt&I1);
		friend std::istream& operator>>(std::istream&iint, BigInt&I1);
		BigInt& operator = (const BigInt &I) {  //重载赋值运算符
			len = I.len;
			sign=I.sign;
			memset(num, 0, sizeof(num));
			for (int i = 1; i <=len; i++)
				num[i] = I.num[i];
			return *this;
		}
		friend BigInt operator+(BigInt&I1, BigInt&I2);
		friend BigInt operator-(BigInt&I1, BigInt&I2);
		friend BigInt operator*(BigInt&I1, BigInt&I2);
		friend BigInt operator/(BigInt I1, BigInt&I2);//大整型除以大整型-减法模拟除法
		friend BigInt operator/(BigInt&I1, int I2);//大整型除以整型-逐位试商法
		friend bool operator<(const BigInt&I1, const BigInt&I2);
		friend bool operator>(const BigInt&I1, const BigInt&I2);
		friend bool operator!=(const BigInt&I1, const BigInt&I2);
		friend bool operator==(const BigInt&I1, const BigInt&I2);
		friend bool operator<=(const BigInt&I1, const BigInt&I2);
		friend bool operator>=(const BigInt&I1, const BigInt&I2);
} BigInt;
bool operator<(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 < len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] < I2.num[i];
	}
	return false;
}
bool operator<=(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 < len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] < I2.num[i];
	}
	return true;
}
bool operator>(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 > len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] > I2.num[i];
	}
	return false;
}
bool operator>=(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return len1 > len2;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return I1.num[i] > I2.num[i];
	}
	return true;
}
bool operator==(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return false;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return false;
	}
	return true;
}
bool operator!=(const BigInt&I1, const BigInt&I2) {
	int len1 = I1.len, len2 = I2.len;
	if (len1 != len2) {
		return true;
	}
	for (int i = len1; i >= 1; i--) {
		if (I1.num[i] != I2.num[i]) return true;
	}
	return false;
}
BigInt operator+(BigInt&I1, BigInt&I2) {
	int L = BigInt::max_Big(I1.len, I2.len) + 1;
	BigInt I3;
	for (int i = 1; i <= L; i++) {
		I3.num[i] = I1.num[i] + I2.num[i];
	}
	I3.flatten(L);
	return I3;
}
BigInt operator-(BigInt&I1, BigInt&I2) {
	int L = BigInt::max_Big(I1.len, I2.len);
	BigInt i1, i2, I3;
	if (I1 < I2) {
		i1 = I2;
		i2 = I1;
		I3.sign = 0;
	} else {
		i1 = I1;
		i2 = I2;
		I3.sign = 1;
	}
	for (int i = 1; i <= L; i++) {
		if (i1.num[i] < i2.num[i]) {
			i1.num[i + 1]--;
			i1.num[i] += 10;
		}
		I3.num[i] = i1.num[i] - i2.num[i];
	}
	while (I3.num[L] == 0 && L > 1) L--;
	I3.len = L;
	return I3;
}
BigInt operator*(BigInt&I1, BigInt&I2) {
	BigInt I3;
	int len1 = I1.len, len2 = I2.len;
	int L = len1 + len2;
	for (int i = 1; i <= len1; i++)
		for (int j = 1; j <= len2; j++) {
			I3.num[i + j - 1] += I1.num[i] * I2.num[j];
		}
	I3.flatten(L);
	return I3;
}
BigInt operator/(BigInt&I1, int I2) {
	BigInt I3;
	int x = 0;
	int len = I1.len;
	for (int i = len; i >= 1; i--) {
		I3.num[i] = (x * 10 + I1.num[i]) / I2;
		x = ((x * 10 + I1.num[i])) % I2;
	}
	I3.flatten(len);
	return I3;
}
BigInt operator/(BigInt I1, BigInt&I2) {
	BigInt I3;
	int len1 = I1.len, len2 = I2.len;
	int start = len1 - len2 + 1;
	for (int i = start; i >= 1; i--) {
		BigInt tmp1, tmp2(10);
		tmp1 = I2;
		while (tmp1.len < i) {
			tmp1 = tmp1 * tmp2;
		}
		while (I1 >= tmp1) {
			I3.num[i]++;
			I1 = I1 - tmp1;
		}
	}
	I3.flatten(start);
	return I3;
}
std::istream& operator>>(std::istream&iint, BigInt&I1) { //重载输入
	std::string s;
	iint >> s;
	I1.len = s.length();
	int cnt = I1.len - 1;
	for (int i = 1; i <= I1.len; i++) {
		I1.num[i] = s[cnt--] - '0';
	}
	return iint;
}
std::ostream& operator<<(std::ostream&iout, BigInt &I1) { //重载输出
	if (!I1.sign) std::cout<< '-';
	for (int i = BigInt::max_Big(I1.len, 1); i >= 1; i--) {
		iout << I1.num[i];
	}
	return iout;
}

#endif

实际演示

将代码包裹成头文件,放在项目文件夹中,即可调用大数型了。

#include "BIGINT.h"
using namespace std;
int main(){
	BigInt I1,I2;
	BigInt I3;
	cin>>I1>>I2;
	I3=I1+I2;
	cout<<"I1+I2="<<I3<<endl;
	I3=I1-I2;
	cout<<"I1-I2="<<I3<<endl;
	I3=I1*I2;
	cout<<"I1*I2="<<I3<<endl;
	I3=I1/I2;
	cout<<"I1/I2="<<I3<<endl;
	return 0;
}

 就这样啦~谢谢观看!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值