版权声明:转载请注明出处。 https://blog.csdn.net/baidu_38304645/article/details/83216137
每当我在C、C++语言中用到大整数的时候,都会羡慕Java的自带大整数类的属性。无奈只好自己动手,丰衣足食了。
从网上学习了大整数类的实现方法,觉得写的挺好的,时间久了不记得从哪位大神的博客里学习的了...在这里记录一下自己的学习过程吧。
高精度大整数类:本类实现了大数的加减乘除四则运算,重载了输入输出运算符,幂运算,大于,小于,大于等于,小于等于,不等于等于,除法是整除,对余数未确切定义,可以进一步完善,处理一些异常情况使得能够更加通用.
辅助宏:
#define POSITIZE 1 //正位(含0)
#define NEGATIVE -1 //负位
大整数类的定义:
struct BigInteger
{
friend BigInteger operator - (BigInteger, BigInteger);
friend BigInteger operator + (BigInteger, BigInteger);
// 表示大数的结构。数位按低位到高位的顺序存放。存储的是数位值,而不是数位的字符值。
vector<int> digits; // 存放数位值
int signbit; // 符号位。
BigInteger();
BigInteger(long long int);
void zero_justify();
BigInteger operator ^ (int);
BigInteger operator << (int);
BigInteger operator += (const BigInteger &);
BigInteger operator -= (const BigInteger &);
BigInteger operator *= (const BigInteger &);
BigInteger operator /= (const BigInteger &);
};
typedef BigInteger BI;
默认构造函数:
BigInteger::BigInteger()
{
//默认构造函数
signbit = POSITIZE;
}
大数类的构造函数 参数为长整数.
BigInteger::BigInteger(long long int a)
{
//大数类的构造函数 参数为整数
signbit = (a >= 0) ? POSITIZE:NEGATIVE;
a = abs(a);
do
{
digits.push_back(a % 10);
a /= 10;
}while(a);
}
重载输入符号>>。
// 重载输入符号>>。
istream & operator >> (istream & in, BigInteger &b)
{
//读入表示大整数的字符串
string s;
in >> s;
if(s.empty()) // 若长度为0,表示读入的是一个空字符串,应该要给予错误提示,并返回
return in;
/* 在解析之前,理应判断该字符串是否是一个合法的大数表示,即开始一位为符号位,为“+”或
“-”,正整数“+”可以忽略,后面应该全部是数字字符,且不包含前导0*/
// 解析符号位。
if(isdigit(s[0]))
b.signbit = POSITIZE;
else
{
b.signbit = (s[0] == '+') ? POSITIZE:NEGATIVE;
s.erase(s.begin());
}
// 解析数字位,从低位到高位存放于动态数组中。
b.digits.clear();
for(int i = s.length() - 1; i >= 0; i--)
b.digits.push_back(s[i] - '0');
b.zero_justify(); //消除前导0
return in;
}
重载输出符号<<。
ostream & operator << (ostream &out, const BigInteger &b)
{
// 当为自然数时,不输出“+”号。
if(b.signbit < 0)
out << '-';
for(int i = b.digits.size() - 1; i >= 0; i--)
out << b.digits[i];
return out;
}
移除大数运算产生的前导0。
void BigInteger::zero_justify()
{
//移除大数运算产生的前导0。
for(int i = digits.size() - 1; i >= 1; i--)
{
if(digits[i])
break;
else
digits.pop_back();
}
if(digits.size() == 1 && digits[0] == 0) //只有一个0
signbit = POSITIZE;
}
左移操作。n 表示左移的位数。即将 大数a 乘以 10^n。
BigInteger BigInteger::operator << (int n)
{
// 左移操作。n 表示左移的位数。即将 a 乘以 10^n。
// 若 a 等于 0,则移位后仍为 0。
if(digits.size() == 1 && digits[0] == 0)
return *this;
// 向左移动 b 位,相当于在数位数组前插入 n 个 0。
for(int i = 0; i < n; i++)
digits.insert(digits.begin(), 0);
return *this;
}
比较两个数的大小,若相等,返回 0,若 a 大于 b,返回 1,若 a 小于 b,返回 -1。
int compare(const BigInteger &a, const BigInteger &b)
{
//比较两个数的大小,若相等,返回 0,若 a 大于 b,返回 1,若 a 小于 b,返回 -1。
// 若 a 为正,b 为负,则有 a 大于 b。
if(a.signbit < b.signbit)
return NEGATIVE;
// 若 a 为负,b 为正,则 a 小于 b。
else if(a.signbit > b.signbit)
return POSITIZE;
// 若两数符号相同,则 a 的数位长度大于 b 的数位长度,若 a 为正数,则有 a 大于 b,若 a
// 为负数,有 a 小于 b,则将 a 的符号位乘以1作为结果返回即可。
if(a.digits.size() > b.digits.size())
return a.signbit * POSITIZE;
// 若两数符号相同,若a的数位长度小于b的数位长度,若 a 为正数,则 a 小于 b,若 a 为负数,
// 则 a 大于 b,则将 a 的符号位乘以 -1 作为结果返回即可。
else if(a.digits.size() < b.digits.size())
return a.signbit * NEGATIVE;
// 两个数的数位长度相等,符号相等,则从低位到高位逐个比较数位值的大小。
for(int i = a.digits.size() - 1; i >= 0; i--)
{
if(a.digits[i] > b.digits[i])
return a.signbit * POSITIZE;
if(a.digits[i] < b.digits[i])
return a.signbit * NEGATIVE;
}
return 0;
}
重载小于符.
bool operator < (const BigInteger &a, const BigInteger &b)
{
//重载小于符
return compare(a, b) < 0;
}
重载小于等于符.
bool operator <= (const BigInteger &a, const BigInteger &b)
{
//重载小于等于符
return compare(a, b) <= 0;
}
重载大于符.
bool operator > (const BigInteger &a, const BigInteger &b)
{
//重载大于符
return compare(a, b) > 0;
}
重载大于等于符.
bool operator >= (const BigInteger &a, const BigInteger &b)
{
//重载大于等于符
return compare(a, b) >= 0;
}
重载等于符.
bool operator == (const BigInteger &a, const BigInteger &b)
{
//重载等于符
return compare(a, b) == 0;
}
重载不等于符.
bool operator != (const BigInteger &a, const BigInteger &b)
{
//重载不等于符
return compare(a, b) != 0;
}
下一篇文章来具体讲解关键的加减乘除等算法的实现。