我的高精日记 #1 2018-8
成功切掉高精度加法,逻辑运算。Code:
struct BN//Big_number
{
#define LEN_SIZE 100001//定义长度
int len;//记录长度
int a[LEN_SIZE];//记录每一位数字
// 结构体中,可以直接调用自己的变量,不用写XX.XX,很方便 OVO!
bool is_nn;//is negative num 记录是否是负数
inline void clear() { is_nn=false , memset(a,0,sizeof a) , len=0 ; return; }//将整个结构体清零 初值:不是负数,0
inline void BN_read()
{
char t=getchar();//感觉getchar()会更快一点
clear();//清空等待读入
for(;!isdigit(t);t=getchar()) if(t=='-') is_nn=true;//不是数字,抛弃字符。如果是负号,把记录变量(is_nn)赋值成真(true)
//isdigit(char _C) 返回布尔值,是否是数字
for(;isdigit(t);t=getchar()) a[++len]=(t-'0');//是数字,把长度加一
return;结束
}
inline void BN_write()
{
if(is_nn) putchar('-');//是负数,输出符号。
for(int i=1;i<=len;++i) putchar(a[i]+'0');//输出字符,感觉putchar()会快一点,从1~长度len枚举输出,下标从1开始
return;
}
template <typename _int>//定义一个类变量-- _int
inline void change(_int A)//将任意类转成高精类(BN)。用_int定义,支持所有类
{
clear();//将载体清空
if(!A)//如果A是0
{
len=1;//零的长度为1
a[1]=0;//第一位是0
is_nn=false;//无符号
return;//返回
}
_int _A=A;//用另一个_int类来记录
if(_A<0) _A=-_A,is_nn=true;//是负数,记录成有符号,取绝对值
for(;_A;++len,_A/=10);//找长度有几位,特判0,不然卡掉循环
_A=A;//因为找完长度_A为0,重新赋值成A。
if(is_nn) _A=-_A;//如果有符号,取绝对值
for(int i=len;i;--i) a[i]=_A%10,_A/=10;//把A的每一位存进存数字的数组中
return;//结束
}
BN operator = (const BN &next)//重载运算符“=”,返回高精类值
{
clear();//同强转类型,清空载体
is_nn=next.is_nn;//转移符号
len=next.len;//转移长度
for(int i=1;i<=next.len;++i) a[i]=next.a[i];//把next的每一位数赋给载体
return *this;//返回自己(*this)。
//*this——C++关键字,返回结构体中的变量,代指自己(结构体)
}
bool operator < (const BN &next) const //返回布尔值,重载“<”号,是否小于next(下一个数)
{
if(!next.is_nn&&!is_nn)//两数同为正数
{
if(len<next.len) return true;//长度比下一个数小,一定比下一个数小
if(len>next.len) return false;//反之,比下一个数大
for(int i=len;i;--i)//确认长度一样,从最高位开始比较
{
if(a[i]<next.a[i]) return true;//找到第i位数比下一个数的第i位数小,就比下一个数小,返回
if(a[i]>next.a[i]) return false;//反之,比下一个数大,返回
if(a[i]==next.a[i]) continue;//两个数相等,跳过以后的循环内容,貌似没了。。。
}//不信找不到。假的
}
else if(next.is_nn&&is_nn)//两数同为负数,以下与判正数完全相反,复制的QAQ
{
if(len<next.len) return false;
if(len>next.len) return true;
for(int i=len;i;--i)
{
if(a[i]<next.a[i]) return false;
if(a[i]>next.a[i]) return true;
if(a[i]==next.a[i]) continue;
}//看上面
}
//两数异号
else if(next.is_nn&&!is_nn) return false;//下一个数是负数,这个是正数,返回比下一个数大
else if(!next.is_nn&&is_nn) return true;//反之,返回比下一个数小
return false;//没找到,说明相等,也不小于,返回
}
template <typename _int>//用于判低精数
bool operator < (const _int &_next) const
{
BN next;
next.change(_next);//转化成高精数再比较
return (*this<next);//都是布尔值,直接返回就可以了
}
bool operator == (const BN &next) const //判相等
{
if(is_nn!=next.is_nn) return false;//位数不同,一定不相等
for(int i=1;i<=len;++i) if(a[i]!=next.a[i]) return false;//发现数位不同,不想等,直接返回
return true;//能跑到这里,欣慰啊,一定相等了,返回
}
template <typename _int>//判低精
bool operator == (const _int &_next) const
{
BN next;
next.change(_next);
return (*this==next);
}
bool operator != (const BN &next) const //判不相等
{
return !(*this==next);//直接返回等于的假值,相等为假,不相等为真
}
template <typename _int>//判低精
bool operator != (const _int &_next) const
{
BN next;
next.change(_next);
return (*this!=next);
}
bool operator > (const BN &next) const //判大于
{
return !((*this)<next&&((*this)!=next));//返回不小于并且不等于
}
template <typename _int>//判低精
bool operator > (const _int &_next) const
{
BN next;
next.change(_next);
return (*this>next);
}
bool operator <= (const BN &next) const//判小于等于
{
return !(*this>next);//不大于即为小于等于
}
template <typename _int>//判低精
bool operator <= (const _int &_next) const
{
BN next;
next.change(_next);
return (*this<=next);
}
bool operator >= (const BN &next) const//判大于等于
{
return !(*this<next);//不小于即为大于等于
}
template <typename _int>//不打了,判低精
bool operator >= (const _int &_next) const
{
BN next;
next.change(_next);
return (*this>=next);
}
bool opeator ! () const//判是否为零
{
for(int LEN=LEN_SIZE-1;LEN!=-1;--LEN) if(a[LEN]) return false;//找到一位不为零,返回
return true;//为零,返回
}
//终于写完了
BN operator + (const BN &next) //高精度加法——模板 自己写的
{
if(!next) return *this;//一个数为0,返回另一个数
if(!(*this)) return next;//同上
BN temp;//返回变量在此
temp.clear();//清空,避免神奇的事情发生
if((next.is_nn&&is_nn)||(!next.is_nn&&!is_nn))//两数同号
{
if(is_nn) temp.is_nn=true;//如果其中一个数为负数,因为两数同号,另一个数一定为负数,判一个就够了
BN A,B;//暂存用的变量A,B
A.clear(),B.clear();//先清空,不急
A.len=len,B.len=next.len;//取长度
int Len=Max(len,next.len),_len=Min(len,next.len),LEN;//取出最大长度,最小长度,和位数
for(int i=1,I=A.len;i<=A.len&&I;++i,--I) A.a[I]=a[i];//把高精数反向存储,方便进位
for(int i=1,I=B.len;i<=B.len&&I;++i,--I) B.a[I]=next.a[i];//同上
for(int i=1;i<=_len;++i)//加到最小长度
{
A.a[i]+=B.a[i];//加上对应的数,可能有进上的数,是加等于
if(A.a[i]>=10) A.a[i]-=10,A.a[i+1]++;//如果大于10,就减去10,取个位,把下一位加1
}
for(int i=_len+1;i<=Len;++i)//把从最小长度到最大长度的位数补上
{
if(A.len<B.len) A.a[i]+=B.a[i];//如果下一个数大,加上位数
if(A.a[i]>=10) A.a[i]-=10,A.a[i+1]++;//处理进位
}
for(LEN=LEN_SIZE-1;!A.a[LEN];--LEN);//从最后一位开始找,直到有不为零的数
//因为是反序存储,0都在后面,倒叙找不会去末尾0,相当于去前导0
temp.len=LEN;//结果的长度是这个值
for(int i=LEN,I=1;I<=LEN&&i;++I,--i) temp.a[i]=A.a[I];//再把它反过来存进结果里
return temp;//返回结果
}
else;//因为减法还没写,不处理两数异号的情况
//目前只能处理同号运算,异号再说吧,会加进去的
}
};