[玩耍]我的整形大数类(支持正负)

好几天没刷题没看书没写博客了,一直在闭关修炼写大数,现在终于写出来啦!我也终于有了属于我自己的大数~~~~并且以头文件的形式写出的,可以算是一个完整的成品了,拿过来就可以用。
本大数类:longer实现的功能:加减乘除、取余、取绝对值,开根号什么的没精力弄了,只是声明了一下没定义,以后会更新的。同时支持正负号。数据用的vector< long long >存储,long long最大储存9位数,也就是999999999,因为2个999999999相乘刚好不越界。不过后来发现好像没必要,用int就行了,但是写都写一半了,就没改。不过灵活性也蛮高的吧,可以很轻松地把数据类型从long long 改为int,同时只要把MAX改为int的最大值10000,把DIGIT改为4即可(没具体试过,应该没问题)。就是下面这几行:

//longer类内定义
typedef long long ll;
static constexpr ll MAX = 1000000000;
static constexpr int DIGIT = 9; 

当然有储存,这应该不是最好的方法,不过就我目前的水平就这样吧。而且现在对于编程是“空间换时间”还是“时间换空间”一直很纠结。。。
然后单独定义一个sign表示正负号。那么当然啦,对于这种用单独一个符号标记来表示正负数字的,就会有+0和-0的问题,我也是基本解决了,就是把负的改成正的。当然不排除还有bug,没精力检测了。后续更新吧。
加法减乘除均使用小学教的竖式方法。。。因为网上也没学到更快的方法,最快的方法(尤其是除法)好像看到个,没会。。。所以这个东西在处理比如一千多位除以几百之类的数据时会很慢。。。不过毕竟我现在还算是新手嘛,以后可以还会再写一个更快的大数。使用竖式时,加法减法乘法使用的10^10进制,即统一算出一个ll(long long)的值,进位到下一个。
加法减法本质上由get_addition()与get_subtraction()实现,这两个函数无视正负号,全都看成是正的进行运算,只支持大的数加减小的数。因此对于有不同的正负符号的数字,比如负+正,可以看作-(正-负),所以只要调用get _subtraction()运算后添个负号即可;而对于正-负,可看作正+正,反而调用get _addition()。所以本质上还是正数之间的运算。
乘法与加法类似,甚至还少了符号的问题。
除法也是小学教的竖式法,一位位除,也就是一位位减,但是由于我得先乘以10的好多次,再循环减,再看下一位,速度还是慢,就比如3000位的数字除以50位的数字,那速度醉啦,要十几秒。
取余使用的”*this - (*this / n)*n”,所以比除号还慢。
比较符号没有很仔细地调试,但是应该没什么问题吧。
截图:
这里写图片描述

这里写图片描述

代码:

//我的大数类,定义为longer好了[笑哭]
#ifndef _LONGER_H
#define _LONGER_H
#include<vector>
#include<string>
#include<sstream>
#include<iomanip>
//#pragma warning(disable:4996) //对使用VS2015且开启了“安全开发生命周期(SDL)检测”的项目奏效(VS2013应该也有用)
class longer
{
    //必要定义  (-.-;)
    typedef long long ll;
    static constexpr ll MAX = 1000000000;   //每个ll的存储限制,999999999*999999999刚好不溢出(9个9)
    static constexpr int DIGIT = 9;         //ll支持的最大位数
    //数据储存  (-.-;)
    bool sign;                              //正负号:0正1负
    std::vector<ll> number;                 //大数存储区

public:
    //构造函数  (-.-;)
    longer();
    longer(const ll&);
    longer(const longer&);
    longer(const char*);
    longer(const std::string&);

    //运算符重载 (-.-;)
    longer operator +()const;
    longer operator +(const longer&)const;
    longer operator -()const;
    longer operator -(const longer&)const;
    longer operator *(const longer&)const;
    longer operator /(const longer&)const;
    longer operator %(const longer&)const;

    longer& operator ++();
    longer operator ++(int);
    longer& operator --();
    longer operator --(int);

    longer& operator =(const ll&);
    longer& operator =(const longer&);
    longer& operator =(const char*);
    longer& operator =(const std::string&);

    longer& operator +=(const longer&);
    longer& operator -=(const longer&);
    longer& operator *=(const longer&);
    longer& operator /=(const longer&);

    inline bool operator <(const longer&)const;
    inline bool operator >(const longer&)const;
    inline bool operator <=(const longer&)const;
    inline bool operator >=(const longer&)const;
    inline bool operator ==(const longer&)const;
    inline bool operator !=(const longer&)const;

    friend std::istream& operator >>(std::istream&, longer&);
    friend std::ostream& operator <<(std::ostream&, const longer&);

    //其他函数  (-.-;)
    int digit()const;
    static longer lrabs(const longer&);     //求绝对值
    static longer lrsqrt(const longer&);    //求算数平方根,暂时没打算完成,先占个茅坑,不拉屎

private:
    //类内部调用 (-.-;)
    longer(const int, const ll&);                                   //分配多少个vector容量,每个数据均为第一个参数
    static longer& get_addition(longer&, const longer&, bool);      //获得加法结果,仅支持正整数以大加小,无视正负号
    static longer& get_subtraction(longer&, const longer&, bool);   //获得减法结果,仅支持正整数以大减小,无视正负号
    int get_comparison(const longer&)const;                         //获得比较结果,仅支持正整数相互比较,无视正负号
    inline ptrdiff_t get_ptrdiff()const;                            //获得vector数组元素个数
    inline longer& get_zero();                                      //若结果为0,且若0的sign为负,则改为0
};



//必要定义  ↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗
constexpr longer::ll longer::MAX;
constexpr int longer::DIGIT;



//构造函数  ↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗
longer::longer() { number.push_back(0); }
longer::longer(const ll& n) { *this = n; }
longer::longer(const longer& n) { *this = n; }
longer::longer(const char* s) { *this = s; }
longer::longer(const std::string& s) { *this = s; }
longer::longer(const int i, const ll& n) : number(i, n), sign(0) {}



//运算符重载 ↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗
//加减乘除取余次方
longer longer::operator +()const { return *this; }

longer longer::operator +(const longer& n)const
{
    bool judge = get_comparison(n) >= 0;
    longer aa(judge ? *this : n);
    auto &bb = (judge ? n : *this);
    if ((!aa.sign) && (!bb.sign)) return get_addition(aa, bb, 0);           //正+正
    if ((!aa.sign) && (bb.sign)) return get_subtraction(aa, bb, !judge);    //正+负
    if ((aa.sign) && (!bb.sign)) return get_subtraction(aa, bb, judge);     //负+正
    return get_addition(aa, bb, 1);                                         //负+负
}

longer longer::operator -()const { longer t(*this);t.sign = (t.sign ? 0 : 1);return t; }

longer longer::operator -(const longer& n)const
{
    bool judge = get_comparison(n) >= 0;
    longer aa(judge ? *this : n);
    auto &bb = (judge ? n : *this);
    if ((!aa.sign) && (!bb.sign)) return get_subtraction(aa, bb, !judge);   //正-正
    if ((!aa.sign) && (bb.sign)) return get_addition(aa, bb, 0);            //正-负
    if ((aa.sign) && (!bb.sign)) return get_addition(aa, bb, 1);            //负-正
    return get_subtraction(aa, bb, judge);                                  //负-负
}

longer longer::operator *(const longer& n)const
{//模拟小学老师教的方法
    int leni = get_ptrdiff(), lenj = n.get_ptrdiff();
    longer re(leni + lenj, 0);
    ll flag;
    sign == n.sign ? re.sign = 0 : re.sign = 1;
    for (int i = 0;i < leni;++i) {
        longer t(n);
        int j;
        flag = 0;
        for (j = 0;j < lenj;++j) {
            t.number[j] = t.number[j] * number[i] + flag;
            flag = t.number[j] / MAX;
            t.number[j] -= flag*MAX;
        }
        if (flag) t.number.push_back(flag);
        flag = 0;
        for (j = 0;j < t.get_ptrdiff();++j) {
            re.number[i + j] += t.number[j] + flag;
            if (re.number[i + j] >= MAX) re.number[i + j] -= MAX, flag = 1;
            else flag = 0;
        }
        if (flag) re.number[i + j] += flag;
    }
    while (re.get_ptrdiff() > 1 && !*re.number.rbegin()) re.number.pop_back();
    return re.get_zero();
}

longer longer::operator /(const longer& n)const
{//模拟小学老师教的方法
    if (n == longer((ll)0)) { std::cerr << "除数为0!\n";exit(1); }
    longer th(*this), re((ll)0);
    re.sign = th.sign = 0;
    const int times = digit() - n.digit();
    for (int i = times;i >= 0;--i) {
        longer digi(i / DIGIT + 1, 0);
        *digi.number.rbegin() = ((ll)pow(10, i % DIGIT));
        longer t(n*digi); t.sign = 0;
        while (th.get_comparison(t) == 1) th-=t, re += digi;
        if (th.get_comparison(t) == 0) { re += digi;break; }
    }
    if (sign != n.sign) re.sign = 1;
    return re.get_zero();
}

longer longer::operator %(const longer& n)const
{
    longer re(*this - (*this / n)*n);
    return re.get_zero();
}


//自增自减
longer& longer::operator ++() { return *this = *this + 1; }
longer longer::operator ++(int) { longer t = *this;*this = *this + 1;return t; }
longer& longer::operator --() { return *this = *this - 1; }
longer longer::operator --(int) { longer t = *this;*this = *this - 1;return t; }


//赋值
longer& longer::operator =(const ll& n)
{
    if (n < 0) sign = 1, number.push_back(-n);
    else sign = 0, number.push_back(n);
    return *this;
}

longer& longer::operator =(const longer& n)
{
    number = n.number;
    sign = n.sign;
    return *this;
}

longer& longer::operator =(const char* s)
{
    return *this = std::string(s);
}

longer& longer::operator =(const std::string& s)
{
    auto ps = s.rbegin();
    char c[DIGIT + 1], *pc;
    ll temp;
    sign = 0;
    while (ps != s.rend()) {
        *(pc = &c[DIGIT]) = '\0';
        int i;
        for (i = 0;i < DIGIT && ps != s.rend();++i)
            *--pc = *ps++;
        if (*(ps - 1) == '-') *pc = '0', sign = 1;
        while (i++ < DIGIT) *--pc = '0';
        std::istringstream in(c);
        in >> temp;
        number.push_back(temp);
    }
    if (get_ptrdiff()>1 && !*number.rbegin()) number.pop_back();
    return *this;
}


longer& longer::operator +=(const longer& n) { return *this = *this + n; }
longer& longer::operator -=(const longer& n) { return *this = *this - n; }
longer& longer::operator *=(const longer& n) { return *this = *this * n; }
longer& longer::operator /=(const longer& n) { return *this = *this / n; }


//比较
inline bool longer::operator <(const longer& n)const
{
    if ((!sign) && (n.sign)) return 0;
    if ((sign) && (!n.sign)) return 1;
    if ((!sign) && (!n.sign)) return get_comparison(n) == -1;
    return get_comparison(n) == 1;
}

inline bool longer::operator >(const longer& n)const
{
    if ((!sign) && (n.sign)) return 1;
    if ((sign) && (!n.sign)) return 0;
    if ((!sign) && (!n.sign)) return get_comparison(n) == 1;
    return get_comparison(n) == -1;
}

inline bool longer::operator <=(const longer& n)const
{
    if ((!sign) && (n.sign)) return 0;
    if ((sign) && (!n.sign)) return 1;
    if ((!sign) && (!n.sign)) return get_comparison(n) <= 0;
    return get_comparison(n) >= 0;
}

inline bool longer::operator >=(const longer& n)const
{
    if ((!sign) && (n.sign)) return 1;
    if ((sign) && (!n.sign)) return 0;
    if ((!sign) && (!n.sign)) return get_comparison(n) >= 0;
    return get_comparison(n) <= 0;
}

inline bool longer::operator ==(const longer& n)const
{
    if (((!sign) && (n.sign)) || ((sign) && (!n.sign))) return 0;
    return !get_comparison(n);
}

inline bool longer::operator !=(const longer& n)const
{
    if (((!sign) && (n.sign)) || ((sign) && (!n.sign))) return 1;
    return get_comparison(n) != 0;
}


//输入输出
std::istream& operator >>(std::istream& is, longer& n)
{
    std::string s;is >> s;
    n = s;
    return is;
}

std::ostream& operator <<(std::ostream& os, const longer& n)
{
    auto p = n.number.rbegin();
    if (n.sign) os << '-';
    os << *p;
    for (++p;p != n.number.rend();++p) {
        int i = 0;auto n = *p;
        while (n /= 10) ++i;
        for (;++i < longer::DIGIT;std::cout << '0');
        os << *p;
    }
    return os;
}



//其他函数  ↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗
int longer::digit()const
{
    int a = (get_ptrdiff() - 1) * DIGIT;
    ll b = *number.rbegin();
    do ++a;while (b /= 10);
    return a;
}

longer longer::lrabs(const longer& n) { longer t(n);if (t.sign) t.sign = 0;return t; }



//类内部调用 ↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗↖(-(●●)-)↗
longer& longer::get_addition(longer& aa, const longer& bb, bool si)
{
    auto a = aa.number.begin(), &aend = aa.number.end();
    auto  b = bb.number.begin(), &bend = bb.number.end();
    bool flag = 0;
    aa.sign = si;
    do {
        *a += (b == bend ? 0 : *b++) + flag;
        if (*a >= MAX) *a -= MAX, flag = 1;
        else if (flag) flag = 0;
    } while (++a != aend && (b != bend || flag));
    if (flag) aa.number.push_back(flag);
    return aa.get_zero();
}

longer& longer::get_subtraction(longer& aa, const longer& bb, bool si)
{
    auto a = aa.number.begin(), &aend = aa.number.end();
    auto  b = bb.number.begin(), &bend = bb.number.end();
    bool flag = 0;
    aa.sign = si;
    do {
        *a -= (b == bend ? 0 : *b++) + flag;
        if (*a < 0) *a += MAX, flag = 1;
        else if (flag) flag = 0;
    } while (++a != aend && (b != bend || flag));
    while (aa.get_ptrdiff()>1 && !*aa.number.rbegin()) aa.number.pop_back();
    return aa.get_zero();
}

int longer::get_comparison(const longer& n)const
{//返回1:左值大,0相等,-1右值大
    if (get_ptrdiff() < n.get_ptrdiff()) return -1;
    if (get_ptrdiff() > n.get_ptrdiff()) return 1;
    auto a = number.rbegin(), b = n.number.rbegin();
    while (a != number.rend()) {
        if (*a < *b) return -1;
        if (*a > *b) return 1;
        ++a, ++b;
    }
    return 0;
}

inline ptrdiff_t longer::get_ptrdiff()const { return number.end() - number.begin(); }

inline longer& longer::get_zero()
{
    if (get_ptrdiff() == 1 && number[0] == 0 && sign == 1) sign = 0;
    return *this;
}


#endif
posted @ 2016-07-25 19:16  蟹脑板  阅读(159)  评论(0编辑  收藏  举报