[玩耍]我的整形大数类(支持正负)
好几天没刷题没看书没写博客了,一直在闭关修炼写大数,现在终于写出来啦!我也终于有了属于我自己的大数~~~~并且以头文件的形式写出的,可以算是一个完整的成品了,拿过来就可以用。
本大数类: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