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 <string>
#include <algorithm>
#include <cassert>
#include <sstream>
#include <memory>
#include <iostream>


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!结果无误。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的 C++ 大数实现,它可以实现大数的加减运算: ``` #include <iostream> #include <string> #include <algorithm> using namespace std; class BigInt { public: string num; BigInt() {} BigInt(string s) { num = s; } BigInt operator+(BigInt b) { BigInt res; int carry = 0; int len1 = num.length(), len2 = b.num.length(); int len = max(len1, len2); for (int i = 0; i < len; i++) { int a = i < len1 ? num[len1 - 1 - i] - '0' : 0; int b = i < len2 ? b.num[len2 - 1 - i] - '0' : 0; int sum = a + b + carry; carry = sum / 10; sum = sum % 10; res.num.insert(0, to_string(sum)); } if (carry) { res.num.insert(0, to_string(carry)); } return res; } BigInt operator-(BigInt b) { BigInt res; int borrow = 0; int len1 = num.length(), len2 = b.num.length(); int len = max(len1, len2); for (int i = 0; i < len; i++) { int a = i < len1 ? num[len1 - 1 - i] - '0' : 0; int b = i < len2 ? b.num[len2 - 1 - i] - '0' : 0; int diff = a - b - borrow; if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } res.num.insert(0, to_string(diff)); } while (res.num.length() > 1 && res.num[0] == '0') { res.num.erase(0, 1); } return res; } void print() { cout << num << endl; } }; int main() { BigInt a("123456789"), b("987654321"); BigInt c = a + b; BigInt d = b - a; c.print(); // 输出 1111111110 d.print(); // 输出 864197532 return 0; } ``` 以上代码实现了 BigInt ,这个包含了 num 字符串,用来存储大数。它的构造函数可以接受一个字符串作为参数,用于初始化大数的 `operator+` 和 `operator-` 分别实现了大数的加法和减法。其,加法的实现比较简单,使用了竖式加法的思想,从低位开始逐位相加,最后将结果逆序输出即可。减法的实现稍微复杂一些,需要考虑借位的情况。 最后,我们在 `main` 函数创建了两个大数 a 和 b,分别进行了加法和减法运算,并将结果打印出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值