C++:大数类BigInt(有符号)

写C++阶乘的时候的,感觉阶乘的增长速度有点超乎我的想象,30!已经超过long long 的范围了。想想其实也是理所当然的事。就自己封装了一个大数类使用。代码如下:

/************************************************* 
Copyright:iwtbam 
Author: iwtbam
Date:2017-11-23 
Description:C++大数类(有符号)
**************************************************/ 
#ifndef __BIG_INT_H__
#define __BIG_INT_H__


#include 
#include 
#include 
#include 
#include 
#include 


class BigInt
{
    public:
        BigInt();
        BigInt(long long num);
        BigInt(const std::string& num);
        BigInt(const BigInt& other);
        ~BigInt()=default;

        friend std::ostream& operator << (std::ostream& os, BigInt num); 
        friend std::istream& operator >> (std::istream& is, BigInt& num);
        BigInt& operator = (const BigInt& other);
        BigInt operator + (BigInt other);
        BigInt operator * (const BigInt& other);
        BigInt operator - (const BigInt& other);
        BigInt operator / (const BigInt& other);
        int abscompare (const BigInt& other);
        bool operator < (const BigInt& other);
        bool operator > (const BigInt& other);
        bool operator <= (const BigInt& other);
        bool operator >= (const BigInt& other);
        bool operator == (const BigInt& other);
        bool operator != (const BigInt& other);
    private:
        BigInt operator * (const int s);
        void squeeze();
    private:
        std::string _num;                 //存储数据
        int sign;                         //符号位
};


#endif //__BIG_INT_H__;
#include "BigInt.h"

BigInt::BigInt()
{
    sign = 0;
    _num = std::string();
};

BigInt::BigInt(long long num)
{
    std::stringstream ss;
    ss << num;
    BigInt(ss.str);
}

BigInt::BigInt(const std::string& num)
{
    sign = 1;
    for(int i = 0;i<num.size();i++)
    {
        if(!i&&num[i]=='-')
        {
            sign = -1;
            continue;
        }
        assert(num[i]<='9'&&num[i]>='0');
    }
    
    if(num.size()==1&&num[0]=='0')
        sign = 0;
    if(sign<0)
        _num = num.substr(1);
    std::reverse(_num.begin(),_num.end());
}

BigInt::BigInt(const BigInt& other)
{
    this->_num = other._num;
    this->sign = other.sign;
}

std::ostream & operator << (std::ostream& os, BigInt num)
{
    std::string tmp = num._num;
    std::reverse(tmp.begin(),tmp.end());
    if(num.sign<0)
        os<<"-";
    return os<<tmp;
}

std::istream& operator >> (std::istream& is, BigInt& num)
{
    is>>num._num;
    num.sign = 1;
    for(int i = 0;i<num._num.size();i++)
    {
        if(!i&&num._num[i]=='-')
        {
            num.sign = -1;
            continue;
        }

        assert(num._num[i]<='9'&&num._num[i]>='0');
    }
    
    if(num._num.size()==1&&num._num[0]=='0')
        num.sign = 0;
    if(num.sign<0)
        num._num = num._num.substr(1);
    std::reverse(num._num.begin(),num._num.end());
    return is;
}

BigInt& BigInt::operator=(const BigInt& other)
{
    this->_num = other._num;
    this->sign = other.sign;
    return *this;
}

BigInt BigInt::operator+(BigInt other)
{

    BigInt rval;
    if(this->sign==other.sign)
        rval.sign = this->sign;
    else
    {
        if(this->sign>0)
        {
            other.sign = 1;
            return *this - other;
        }
        else
        {
            BigInt temp(*this);
            temp.sign = 1;
            return other - temp;
        }

    }
    int len1 = this->_num.size();
    int len2 = other._num.size();
    int len = std::max(len1,len2);

    std::stringstream ss;
    int i(0),bit(0);
    for(;i<len;i++)
    {
        char a = i<len1?this->_num[i]:'0';
        char b = i<len2?other._num[i]:'0';
        char result = a+b+bit-'0';
        if(result>'9')
        {
            result -= 10;
            bit = 1;
        }
        else
            bit = 0;
        ss<<result;
    }
    if(bit)
        ss<<bit;
    rval._num.append(ss.str());
    return rval;
 
}


BigInt BigInt::operator*(const int s)
{
    BigInt rval;
    std::stringstream ss;
    int bit(0);
    for(int i=0;i<(*this)._num.size();i++)
    {
        int result = ((*this)._num[i]-'0')*s+bit;
        if(result>9)
        {
            bit = result/10;
            result = result%10;
        }
        else
        {
            bit = 0;
        }
        ss<<result;
    }
    if(bit)
        ss<<bit;
    rval._num.append(ss.str());
    return rval;
}

BigInt BigInt::operator*(const BigInt& other)
{
    BigInt rval,temp;
    int size = other._num.size();
    for(int i = 0;i<size;i++)
    {
        temp = (*this)*(other._num[i]-'0');
        for(int j = 0;j<i;j++)
        {
            temp._num.insert(0,"0");
        }
        rval = rval + temp;
    }
    rval.sign = this->sign * other.sign;
    return rval;
}

BigInt BigInt::operator - (const BigInt& other)
{
    BigInt rval;
    std::string max = this->_num;
    std::string min = other._num;

    if(this->sign==other.sign)
    {
        int result = this->abscompare(other);
        if(result==1)
        {
            rval.sign = this->sign;
        }
        else if(result==-1)
        {
            rval.sign = -other.sign;
            min = this->_num;
            max = other._num;
        }
        else
        {
            rval.sign = 0;
            rval._num.append("0");
            return rval;
        }
    }
    else if(this->sign > other.sign)
    {
        rval.sign = 1;
        rval._num = this->_num;
        BigInt temp(other);
        temp.sign = 1;
        return rval + temp;
    }
    else
    {
        rval.sign = -1;
        rval._num = this->_num;
        BigInt temp(other);
        temp.sign = -1;
        return rval + temp;
    }

    int bit(0);
    std::stringstream ss;
    int i(0);
    for(;i<max.size();i++)
    {
        char a = max.at(i);
        char b = i<min.size()?min.at(i):'0';
        char result;
        if((a-bit)>=b)
        {
            result = a-bit-b+'0';
            bit = 0;
        }
        else
        {
            result = a+10-b-bit+'0';
            bit = 1;
        }
        ss<<result;
    }
    ss>>rval._num;
    rval.squeeze();
    return rval;
}

BigInt BigInt::operator / (const BigInt& other)
{

    assert(!(BigInt("0")==other));
    BigInt temp("0"),i(1),j(1), otemp(other);
    otemp.sign = 1;
    temp.sign = 1;
    for(;temp.abscompare(*this)<0;i = i+1)
    {
        temp =temp + i * otemp;
        j = j+i;
    }
    for(;temp.abscompare(*this)>0&&j>1;j=j-1)
    {
        temp = temp - otemp;
    }
    j = j-1;
    j.sign = this->sign * other.sign;
    if(!j.abscompare(0))
        j.sign = 0;
    return j;
}

int BigInt::abscompare(const BigInt& other)
{

    if(this->_num.size()> other._num.size())
        return 1;
    if(this->_num.size()< other._num.size())
        return -1;

    std::string temp1 = this->_num;
    std::string temp2 = other._num;
    std::reverse(temp1.begin(), temp1.end());
    std::reverse(temp2.begin(), temp2.end());
    if(temp1>temp2)
        return 1;
    else if(temp1==temp2)
        return 0;
    else
        return -1;
}

bool BigInt::operator < (const BigInt& other)
{
   BigInt temp = *this - other;
   return temp.sign < 0;
}

bool BigInt::operator > (const BigInt& other)
{
    BigInt temp = *this - other;
    return temp.sign > 0;
}

bool BigInt::operator <= (const BigInt& other)
{
    return  !((*this) > other);
}

bool BigInt::operator >= (const BigInt& other)
{
    return  !((*this) < other);
}

 bool BigInt::operator == (const BigInt& other)
 {
     return !(*this<other) && !(*this>other);
 }


void BigInt::squeeze()
{
    bool iscontinue = true;
    for(int i = _num.size()-1;i>=1&&iscontinue;i--)
    {
        if(_num[i]=='0')
        {
            _num[i] = 0;
            continue;
        }
        iscontinue = false;
    }
}

写完后百度发现基本都用int数组封装的,想想确实比std::string更为方便一些。

测试了几个用例,基本没什么问题。
实际计算的效果还可以,运行10000!结果无误。

你可能感兴趣的:(C++,算法)