数据结构-高精度大整数(一)

版权声明:转载请注明出处。 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;
}

下一篇文章来具体讲解关键的加减乘除等算法的实现。

猜你喜欢

转载自blog.csdn.net/baidu_38304645/article/details/83216137