大整数类

这一次整理了一下大整数类,学了算法设计上的大整数类,感觉挺不错的,但是不太懂,所以今晚照着网上的一个敲一下,因为我看懂了那个。
嘿嘿,借着这个机会也学一下STL中的队列

        所谓大整数类,就是为了计算那些很大的数,如果这些数用一般的数据类型会发生溢出现象,无法计算,所以才引入了大整数类。
        大整数类的运算原理:
        模拟普通的竖式运算,然后考虑进位和借位。
        存,数组或字符串

 

        算,一位一位的算。

 

不要看着代码这么多,其实看懂了一个,基本上差不多

#include<iostream>
//#include"BigInteger/BigInteger.h"
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<deque>
#include<iterator>
#include<algorithm>
using namespace std;


typedef long long LLT;


//声明大整数类
class BigInteger
{
public:
    //构造函数
    BigInteger():num(), negative(false){}
    BigInteger(const LLT);
    BigInteger(const char *);
    BigInteger(const string);
    BigInteger(const BigInteger &x);


    //运算及输入输出
    BigInteger &operator =(const BigInteger &);
    friend istream &operator >>(istream &,BigInteger &);
    friend ostream &operator <<(ostream &,BigInteger);


    //比较运算
    bool operator > (const BigInteger &) const;
    bool operator < (const BigInteger &) const;
    bool operator == (const BigInteger &) const;
    bool operator >= (const BigInteger &) const;
    bool operator <= (const BigInteger &) const;


    //绝对值与取反运算
    friend const BigInteger abs(const BigInteger &);
    const BigInteger operator - () const;


    //四则运算
    const BigInteger operator + (const BigInteger &) const;
    const BigInteger operator - (const BigInteger &) const;
    const BigInteger operator * (const BigInteger &) const;
    const BigInteger operator / (const LLT &) const;


    //取模运算
    const LLT operator % (const LLT &) const;


private:
    deque<int>num;   //存那些数
    bool negative;    //确定符号
};


///相关定义
//构造函数
BigInteger::BigInteger(const LLT x)
{
    LLT t=abs(x);
    negative = x >= 0 ? false : true;
    while(t > 0)
    {
        num.push_back(t % 10);
        t /= 10;
    }
}
BigInteger::BigInteger(const char* str)
{
    unsigned i = str[0] == '-' ? 1 : 0;
    this->negative = (str[0] == '-' ? true : false);
    for(; i < strlen(str); i++)
        num.push_back(str[i] - '0');
}
BigInteger::BigInteger(const string str)
{
    unsigned i= str[0] == '-' ? 1 : 0;
    this->negative = (str[0] == '0' ? true : false);
    for(; i < str.length(); ++i)
    {
        num.push_back(str[i] - '0');
    }
}
BigInteger::BigInteger(const BigInteger &x):num(x.num),negative(x.negative){}


//运算
BigInteger & BigInteger::operator = (const BigInteger &x)
{
    negative = x.negative;
    num = x.num;
    return (*this);
}
istream & operator >> (istream & in, BigInteger &x)
{
    string str;
    in >> str;
    x = str;
    return in;
}
ostream & operator << (ostream &out, BigInteger x)
{
    if(x.negative) out << '-';
    for(unsigned i = 0; i != x.num.size(); i++)
        out << x.num[i];
    return out;
}


//比较运算
bool BigInteger:: operator > (const BigInteger & rhs) const
{
    BigInteger x = (*this), y = rhs;
    //讨论运算符
    if(!x.negative && y.negative) return true;      //x正y负
    if(x.negative && !y.negative) return false;      //x负y正
    if(x.negative && y.negative) swap(x,y);         //都是负的,交换
    if(x.num.size() > y.num.size()) return true;    //x的位数多
    if(x.num.size() < y.num.size()) return false;   //y的位数多
    for(unsigned i = 0; i != x.num.size(); ++i)
    {
        if(x.num[i] > y.num[i]) return true;
        if(x.num[i] < y.num[i]) return false;
    }


    return false;
}
bool BigInteger::operator < (const BigInteger & rhs) const
{
    return rhs > *this;
}
bool BigInteger::operator == (const BigInteger & rhs) const
{
    return negative ==rhs.negative && num == rhs.num;
}
bool BigInteger::operator >= (const BigInteger & rhs) const
{
    return *this > rhs || *this ==rhs;
}
bool BigInteger::operator <= (const BigInteger & rhs) const
{
    return rhs >= *this;
}


//取反与绝对值运算
const BigInteger abs(const BigInteger &rhs)
{
    BigInteger res;
    res.negative = false;
    res.num = rhs.num;
    return res;
}
const BigInteger BigInteger::operator - () const
{
    BigInteger ret = *this;
    ret.negative = !ret.negative;
    return ret;
}


//四则运算
const BigInteger BigInteger::operator + (const BigInteger &y) const
{
    //讨论符号
    if(!this->negative && y.negative) return *this - abs(y);
    if(this->negative && !y.negative) return y - abs(*this);
    if(this->negative && y.negative) return -(abs(*this) + abs(y));
    BigInteger x = *this, res;
    int temp = 0;
    for(int i = x.num.size() - 1, j = y.num.size();i >= 0||j >= 0;--i, --j)         //加法运算原理  从最后一位两者相加,余数进队列,商进前一位
    {
        int a = i < 0 ? 0 : x.num[i];
        int b = j < 0 ? 0 : y.num[j];
        res.num.push_front((a + b + temp) % 10);   //余数         往前放
        temp = (a + b + temp) / 10;          //商
    }
    if(temp != 0)
        res.num.push_front(temp);         //如果最后还有进位,放在最前面
    return res;
}
const BigInteger BigInteger::operator - (const BigInteger &y) const     //减法运算原理 绝对值运算,先倒过来,然后从第一位开始,上下相减,再重新遍历一遍,如果发现负的,加10,前一位减一
{
    //讨论符号
    if(!this->negative && y.negative) return *this + abs(y);
    if(this->negative && !y.negative) return -(abs(*this)+y);
    if(this->negative && y.negative) return abs(y)-abs(*this);
    deque<int>a, b, res;
    BigInteger ret;
    copy(this->num.begin(), this->num.end(), front_inserter(a));           //倒过来
    copy(y.num.begin(), y.num.end(), front_inserter(b));
    if(y > *this)
    {
        swap(a, b);          //绝对值大的放到a上
        ret.negative = true;
    }
    res.resize(max(a.size(), b.size()) + 5);                //重新定义队列的大小
    for(unsigned i = 0, j = 0;i < a.size() || j < b.size(); ++i, ++j)
    {
        int m = i < a.size() ? a[i] : 0;
        int n = j < b.size() ? b[i] : 0;
        res[i] = m - n;                                //先减
    }
    for(unsigned i = 0;i < res.size()-1; ++i)
    {
        if(res[i] < 0)
        {
            res[i] = res[i] + 10;                                  //如果发现负的,说明不够减,借位
            res[i+1]--;
        }
    }
    while (res.size() >= 2 && res.back() == 0)              //后面的0去掉,因为待会要倒过来才是解,就成了前面的0了
    {
        res.pop_back();
    }
    reverse(res.begin(), res.end());            //倒过来得到答案
    ret.num = res;
    return ret;
}
const BigInteger BigInteger::operator * (const BigInteger &y) const  //乘法原理  先不考虑进位,先存,相应的位相乘,得到最后的结果, 然后满十的往前进
{
    deque<int>a, b, res;
    copy(this->num.begin(), this->num.end(), front_inserter(a));         //倒过来
    copy(y.num.begin(), y.num.end(), front_inserter(b));
    res.resize(a.size() + b.size() + 5);
    for(unsigned i = 0; i < a.size(); ++i)
        for(unsigned j = 0; j<b.size(); ++j)
         res[i+j] = res[i+j] + a[i] * b[j];                  //相应的位上相乘,放好,这个时候没有考虑进位
    for(unsigned i = 0; i < res.size() - 1; ++i)
    {
        res[i+1] = res[i+1] + res[i] / 10;                    //这个时候考虑进位
        res[i] = res[i] % 10;                //进位之后取余
    }
    while(res.size() && res.back() == 0)           //去掉前面的0
        res.pop_back();
    reverse(res.begin(), res.end());
    BigInteger ret;
    ret.negative = this->negative ^ y.negative;               //符号是两个数异或得来的
    ret.num = res;
    return ret;
}
const BigInteger BigInteger::operator / (const LLT & rhs) const       //除法运算 从最低位开始,除,如果不够,加一位,再一次,慢慢的往高位
{
    LLT temp = 0;
    BigInteger x = (*this), res;
    res.negative = this->negative ^ (rhs < 0 ? 1 : 0);    //确定符号
    int y = abs(rhs);
    for(unsigned i = 0;i < x.num.size(); ++i)
    {
        temp = temp * 10 + x.num[i];
        res.num.push_back((int)(temp / y));
        temp %= y;
    }
    while (res.num.size() >= 2 && res.num.front() == 0)             //把前面的0去掉
        res.num.pop_front();
    return res;
}


//取模运算
const LLT BigInteger::operator % (const LLT & y) const
{
    LLT res = 0;
    for(unsigned i = 0; i < this->num.size(); ++i)
        res = (res * 10 + this->num[i]) % y;
    return res;
}



//测试用
int main()
{


    BigInteger a;
    LLT b;
    while(cin >> a >> b)
        cout << a / b << endl;
    return 0;

}




附加一个说明:

我上面头文件里面注释掉的那个,是我把大整数类的定义和实现封装到了一个头文件中,如果想用的话直接引入那个头文件即可,就是把那些定义啥的封装了起来,

 

就像这样,如果想封装的话,就需要自己定义一个头文件,然后把定义实现那些复制到头文件中,然后把头文件添加到codeblock路径中。下面我说一下怎么添加头文件到codeblock路径:

 

1.添加头文件:依次点击project->bulid options->Search directories,在该标签页中点击Compiler,单击Add按钮添加头文件路径

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值