c++高精度整数类

/*
//Name: bigint.h
//Author:zgx(洛谷:zzwdsj)
//Date: 18/07/24 07:26
//Description:这个头文件中的bigint类为高精度数字类,
//机翻:The bigint class in this header file is a high-precision numeric class,
//可以处理int,long,long long,unsigned等基本类型的数字,也可以处理高精度数,并且可以处理负数。
//机翻:It can handle basic types of numbers such as int, long, long long, unsigned, high-precision numbers,
//and negative numbers.
*/
#ifndef BIGINT_H
#define BIGINT_H
/*引入头文件*/
#include<iostream>
#include<vector>
#include<utility>
/*高精度数字类*/
class bigint{
private:
	std::vector<int> num;//用来存储数的绝对值
	bool isNeg,isNumber;//isNeg表示是否是负数,isNumber表示是是合法的整数
public:
    /*无参构造函数*/
	bigint(){
		num.clear();//清空
		isNeg=false;//未赋值的数不是负数
		isNumber=false;//未赋值的数不是一个合法的整数
	}
	/*处理进位*/
	bigint& check(){
		while(num.size()>1&&num.back()==0)num.pop_back();
		if(num[0]==0&&num.size()==1)isNeg=false;
		if(num.back()==0)return *this;//处理完之后直接返回自身
		for(int i=1;i<num.size();i++){
			num[i]+=num[i-1]/10;
			num[i-1]%=10;
		}
		while(num.back()>=10){
			num.push_back(num.back()/10);
			num[num.size()-2]%=10;
		}
		return *this;//处理完之后直接返回自身
	}
	/*有符号类型构造函数*/
	bigint(int x){//以int为入参的构造函数
		num.clear();
		if(x<0)x=-x,isNeg=true;//处理x是负数的情况
		else isNeg=false;
		int x2=x;
		while(x2!=0){//将x的每一位分离
			num.push_back(x2%10);
			x2/=10;
		}
		isNumber=true;
		if(x==0)num.push_back(0);
	}
	bigint(long x){//以long为入参的构造函数
		num.clear();
		if(x<0)x=-x,isNeg=true;
		else isNeg=false;
		long x2=x;
		while(x2!=0){
			num.push_back(x2%10);
			x2/=10;
		}
		isNumber=true;
		if(x==0)num.push_back(0);
	}
	bigint(long long x){//以long long为入参的构造函数
		num.clear();
		if(x<0)x=-x,isNeg=true;
		else isNeg=false;
		long long x2=x;
		while(x2!=0){
			num.push_back(x2%10);
			x2/=10;
		}
		isNumber=true;
		if(x==0)num.push_back(0);
	}
	/*无符号类型构造函数*/
	bigint(unsigned x){//以unsigned为入参的构造函数
		num.clear();
		unsigned x2=x;
		while(x2!=0){
			num.push_back(x2%10);
			x2/=10;
		}
		isNumber=true;
		if(x==0)num.push_back(0);
	}
	bigint(unsigned long x){//以unsigned long为入参的构造函数
		num.clear();
		unsigned long x2=x;
		while(x2!=0){
			num.push_back(x2%10);
			x2/=10;
		}
		isNumber=true;
		if(x==0)num.push_back(0);
	}
	bigint(unsigned long long x){//以unsigned long long为入参的构造函数
		num.clear();
		unsigned long long x2=x;
		while(x2!=0){
			num.push_back(x2%10);
			x2/=10;
		}
		isNumber=true;
		if(x==0)num.push_back(0);
	}
	/*字符/字符串类型构造函数*/
	bigint(char x){//以char为入参的构造函数存储x的ascll码
		num.clear();
		num.push_back(x);
		check();
		isNumber=true;
		if(x==0)num.push_back(0);
	}
	bigint(std::string s){//以string为入参的构造函数存储s对应的整数
		num.clear();
		isNeg=false;
		int leftIndex=0,i=s.size()-1;//如果前面有不合法的字符则去掉
		while(s[leftIndex]>'9'||s[leftIndex]<'0'){
			if(s[leftIndex]=='-')isNeg=!isNeg;
			leftIndex++;
		}
		num.clear();//清空
		bool flag=true;
		for(i=s.size()-1;i>=leftIndex;i--){
			if(s[i]>'9'||s[i]<'0'){
				flag=false;
				break;
			}//处理s不合法的情况
			num.push_back(s[i]-'0');
		}
		if(flag)isNumber=true;//如果s合法改变isNumber的值
	}
    /*重载正负号*/
	bigint operator+(){
		bigint res=*this;
		return res;
	}
	bigint operator-(){
		bigint res=*this;
		res.isNeg=!res.isNeg;
		return res;
	}
    /*绝对值*/
    static bigint abs(bigint& x){//四则运算都会用到的绝对值函数
        bigint res=x;
		if(res.isNeg)return -res;
        return +res;
    }
    /*声明友元*/
	friend bigint operator+=(bigint&,bigint);friend bigint operator+(bigint,bigint);
	friend bigint operator-=(bigint&,bigint);friend bigint operator-(bigint,bigint);
	friend bigint operator*(bigint,bigint);friend bigint operator*=(bigint&,bigint);
	friend bigint operator/(bigint,bigint);friend bigint operator/=(bigint&,bigint);
	friend bigint operator%(bigint,bigint);friend bigint operator%=(bigint&,bigint);//将四则运算与模的重载声明为友元函数
	friend bigint tobinary(bigint);friend bigint todecimal(bigint);//将十进制与二进制的互转声明为友元函数
	friend bigint operator&(bigint,bigint);friend bigint operator&=(bigint&,bigint);
	friend bigint operator|(bigint,bigint);friend bigint operator|=(bigint&,bigint);
	friend bigint operator~(bigint);
	friend bigint operator^(bigint,bigint);friend bigint operator^=(bigint&,bigint);
	friend bigint operator<<(bigint,bigint);friend bigint operator<<=(bigint&,bigint);
	friend bigint operator>>(bigint,bigint);friend bigint operator>>=(bigint&,bigint);//将位运算的重载声明为友元函数
	friend std::ostream& operator<<(std::ostream&,const bigint&);//将输入输出的重载声明为友元函数
	friend std::istream& operator>>(std::istream&,bigint&);
	friend bool operator==(const bigint &a,const bigint &b);
	friend bool operator!=(const bigint &a,const bigint &b);
	friend bool operator<(const bigint &a,const bigint &b);
	friend bool operator>(const bigint &a,const bigint &b);
	friend bool operator<=(const bigint &a,const bigint &b);
	friend bool operator>=(const bigint &a,const bigint &b);//将关系运算符的重载声明为友元函数
	friend bool operator&&(const bigint &a,const bigint &b);
	friend bool operator||(const bigint &a,const bigint &b);
	friend bool operator!(const bigint &a);//将逻辑运算符的重载声明为友元函数
	friend bigint qpow(bigint,bigint);//将快速幂声明为友元函数
	protected:
	    friend bigint div(bigint,bigint,bool);
};
/*重载输入输出*/
std::istream& operator>>(std::istream& is,bigint& n)//重载输入
{
	std::string s;
	is>>s;
	n.isNeg=false;
	int leftIndex=0,i=s.size()-1;//如果前面有不合法的字符则去掉
	while(s[leftIndex]>'9'||s[leftIndex]<'0'){
		if(s[leftIndex]=='-')n.isNeg=!n.isNeg;
		leftIndex++;
	}
	n.num.clear();//清空
	bool flag=true;
	for(i=s.size()-1;i>=leftIndex;i--){
		if(s[i]>'9'||s[i]<'0'){
		    flag=false;
		    break;
		}//处理s不合法的情况
		n.num.push_back(s[i]-'0');
	}
	if(i<=leftIndex)n.isNumber=true;//如果s合法改变isNumber的值
	return is;
}
std::ostream& operator<<(std::ostream& os,const bigint& n){	//重载输出
	if(!n.isNumber)os<<"error";//如果n不是一个合法的数字输出"error"
	else{
		if(n.isNeg)os<<"-";//如果n是负数输出"-"
		for(int i=n.num.size()-1;i>=0;i--)os<<n.num[i];//倒序输出
	}
	return os;
}
/*重载关系运算符*/
bool operator==(const bigint& a,const bigint& b){//重载==
	if(a.num.size()!=b.num.size())return false;//如果位数不同则不等于
	if(a.isNeg!=b.isNeg)return false;//如果符号不同则不等于
	for(int i=a.num.size()-1;i>=0;i--)//逐位比较
		if(a.num[i]!=b.num[i])return false;
	return true;
}
bool operator!=(const bigint &a,const bigint &b){//重载!=
	return !(a==b);
}
bool operator<(const bigint &a,const bigint &b){//重载<
	if(a.isNeg||b.isNeg){//有负数单独判断
		if(a.isNeg&&!b.isNeg)return true;//负数一定比正数小
		if(!a.isNeg&&b.isNeg)return false;//正数移动比负数大
		if(a.num.size()!=b.num.size())return a.num.size()>b.num.size();//位数不同则比较位数
		for(int i=a.num.size()-1;i>=0;i--)//逐位比较
			if(a.num[i]!=b.num[i])return a.num[i]>b.num[i];
	}
	else{
		if(a.num.size()!=b.num.size())return a.num.size()<b.num.size();//位数不同则比较位数
		for(int i=a.num.size()-1;i>=0;i--)//逐位比较
			if(a.num[i]!=b.num[i])return a.num[i]<b.num[i];
	}
	return 0;
}
bool operator>(const bigint &a,const bigint &b){//重载<
	return b<a;
}
bool operator<=(const bigint &a,const bigint &b){//重载<=
	return !(a>b);
}
bool operator>=(const bigint &a,const bigint &b){//重载>=
	return !(a<b);
}
/*重载逻辑运算符*/
bool operator&&(const bigint &a,const bigint &b){
	return (a!=0)&&(b!=0);
}
bool operator||(const bigint &a,const bigint &b){
	return (a!=0)||(b!=0);
}
bool operator!(const bigint &a){
	return !(a!=0);
}
/*重载加*/
bigint operator+=(bigint &a,bigint b){//重载+=
	if(!a.isNeg&&b.isNeg)return a=(a-=(-b));//正数a+负数b=a-(-b)
	if(a.isNeg&&!b.isNeg)return a=(b-=(-a));//负数a+正数b=正数b+负数a=b-(-a)
	if(a.num.size()<b.num.size())a.num.resize((int)b.num.size(),0);//如果不够位数补齐
	for(int i=0;i!=b.num.size();i++)a.num[i]+=b.num[i];//逐位相加
	return a.check();//处理进位
}
bigint operator+(bigint a,bigint b){//重载+
	return a+=b;
}
/*重载减*/
bigint operator-=(bigint &a,bigint b){//重载-=
	if(b.isNeg)return a=(a+(-b));//正数a-负数b=a+(-b)
	if(a.isNeg)return a=-((-a)+b);//负数a-正数b=-((-a)+b)
	if(a<b){//如果a<b则交换并且变号
		bigint t;t=a;a=b;b=t;
		a.isNeg=true;
	}
	if(a.num.size()<b.num.size())a.num.resize((int)b.num.size(),0);//如果不够位数补齐
	for(int i=0;i!=b.num.size();i++){
	    a.num[i]-=b.num[i];//逐位相减
	    if(a.num[i]<0){//处理退位
	        a.num[i]+=10;
	        a.num[i+1]--;
	    }
	}
	return a.check();
}
bigint operator-(bigint a,bigint b){//重载-
	return a-=b;
}
/*重载乘*/
bigint operator*(bigint a,bigint b){//重载*
    bigint ans(0);//初始化存放答案的bigint类
    if(a.isNeg==b.isNeg)ans.isNeg=false;//同号为正
    else ans.isNeg=true;//异号为负
    ans.num.resize((int)a.num.size()+b.num.size(),0);
    for(int i=0;i<a.num.size();i++){
        for(int j=0;j<b.num.size();j++){
            ans.num[i+j]+=a.num[i]*b.num[j];
        }
    }
    return ans.check();
}
bigint operator*=(bigint& a,bigint b){
	return a=a*b;
}
/*重载除*/
bigint div(bigint a,bigint b,bool mode){//返回a除以b的商或余数
    //初始化
    bigint cur(0);//存储余数
    bigint quo(0);//存储商
    cur.num.pop_back();
    quo.isNumber=true;
    if(a.isNeg==b.isNeg)quo.isNeg=false;//同号为正
    else quo.isNeg=true;//异号为负
    cur.isNeg=a.isNeg;//在c+的int中余数一般与被除数同号
    quo.num.resize((int)a.num.size(),0);//商的位数最多为被除数的位数
    for(int i=a.num.size()-1;i>=0;i--){//从高位开始除
        cur=cur*10+a.num[i];//余数进位
        while(cur>=b){//如果余数大于等于除数
            cur-=b;//减去除数
            quo.num[i]++;//商加一
        }
    }
    if(quo==0)quo.isNeg=false;
    if(cur==0)cur.isNeg=false;
    if(!mode)return quo.check();//如果mode为0则返回商
    else return cur.check();//如果mode为1则返回余数
}
bigint operator/(bigint a,bigint b){//重载/
	return div(a,b,0);
}
bigint operator/=(bigint& a,bigint b){//重载/=
	return a=div(a,b,0);
}
bigint operator%(bigint a,bigint b){//重载%
	return div(a,b,1);
}
bigint operator%=(bigint& a,bigint b){//重载%=
	return a=div(a,b,1);
}
bigint operator++(bigint &a){//重载++(前置)
    return a+=1;
}
bigint operator--(bigint &a){//重载--(前置)
    return a-=1;
}
bigint operator++(bigint &a,int){//重载++(后置)
    bigint t=a;
    a+=1;
    return t;
}
bigint operator--(bigint &a,int){//重载--(后置)
    bigint t=a;
    a-=1;
    return t;
}
bigint tobinary(bigint a){//将a转换成二进制
    bigint ret;//结果
    ret.isNeg=a.isNeg;//二进制数与原数同号
    ret.isNumber=a.isNumber;
    while(a!=0){//倒取余数求二进制原码
        ret.num.push_back(a.num[0]%2);
		a/=2;
	}
    if(ret.isNeg){//如果是负数求反码+1
    	for(int i=0;i<ret.num.size();i++)ret.num[i]=!ret.num[i];//求反码
    	ret.num[0]++;//加一
    	int i=0;
    	while(ret.num[i]>1&&i+1<ret.num.size())ret.num[i+1]++,ret.num[i++]%=2;
    	if(ret.num.back()>1)ret.num.push_back(1),ret.num[ret.num.size()-2]=ret.num.back()%2;//处理进位
	}
    return ret;//由于二进制数以补码存储,不去前导零
}
bigint todecimal(bigint a){//将a转换成十进制
    bigint res(0);//结果
    if(a.isNeg){//如果是负数减一后求反码得到原码
    	a.num[0]--;//减一
    	int i=0;
    	while(res.num[i]<0)res.num[i+1]--,res.num[i++]+=2;
    	for(int i=0;i<a.num.size();i++)a.num[i]=!a.num[i];//处理退位
	}
    for(int i=a.num.size()-1;i>=0;i--)res=res*2+a.num[i];//转化成十进制
    res.isNeg=a.isNeg;//十进制数与原数同号
    return res.check();
}
/*重载位运算*/
bigint operator&(bigint a,bigint b){//重载&
    a=tobinary(a);//将a转二进制
	b=tobinary(b);//将b转二进制
    bigint res=a;//最开始结果=a
    if(!res.isNeg)res.num.resize((int)b.num.size(),0);//如果不够位正数补0,
    else res.num.resize((int)b.num.size(),1);//负数补1
    for(int i=0;i<res.num.size();i++)res.num[i]&=b.num[i];//逐位求与
    res.isNeg&=b.isNeg;//符号位求与
    res=todecimal(res);//转回十进制
    return res.check();
}
bigint operator&=(bigint& a,bigint b){//重载&=
    return a=a&b;
}
bigint operator|(bigint a,bigint b){//重载|
    a=tobinary(a);//将a转二进制
	b=tobinary(b);//将b转二进制
    bigint res=a;//最开始结果=a
    if(!res.isNeg)res.num.resize((int)b.num.size(),0);//如果不够位正数补0,
    else res.num.resize((int)b.num.size(),1);//负数补1
    for(int i=0;i<res.num.size();i++)res.num[i]|=b.num[i];//逐位求或
    res.isNeg|=b.isNeg;//符号位求或
    res=todecimal(res);//转回十进制
    return res.check();
}
bigint operator|=(bigint& a,bigint b){//重载|=
    return a=a|b;
}
bigint operator~(bigint a){//重载~
    a=tobinary(a);//将a转二进制
    bigint res=a;//最开始结果=a
    for(int i=0;i<res.num.size();i++)res.num[i]=!res.num[i];//逐位取反
    res.isNeg=!res.isNeg;//符号位取反
    res=todecimal(res);//转回十进制
    return res.check();
}
bigint operator^(bigint a,bigint b){//重载^
    a=tobinary(a);//将a转二进制
    b=tobinary(b);//将b转二进制
    bigint res=a;//最开始结果=a
    if(!res.isNeg)res.num.resize((int)b.num.size(),0);//如果不够位正数补0,
    else res.num.resize((int)b.num.size(),1);//负数补1
    for(int i=0;i<res.num.size();i++)res.num[i]^=b.num[i];;//逐位求异或
    res.isNeg^=b.isNeg;//符号位求异或
    res=todecimal(res);//转回十进制
    return res.check();
}
bigint operator^=(bigint& a,bigint b){//重载^=
    return a=a^b;
}
bigint qpow(bigint a,bigint b){//快速幂
    bigint res=1;//结果
    while(b!=0){
        if(b.num[0]%2)res*=a;//这一位二进制是1则结果乘以a
        a*=a;//a扩大
        b/=2;//继续求下一位二进制
    }
    return res;
}
bigint operator<<(bigint a,bigint b){//重载<<
    return a*qpow(2,b);//与a<<b等价
}
bigint operator<<=(bigint& a,bigint b){//重载<<=
    return a=a<<b;
}
bigint operator>>(bigint a,bigint b){//重载>>
    return a/qpow(2,b);//与a>>b等价
}
bigint operator>>=(bigint& a,bigint b){//重载>>=
    return a=a>>b;
}
#endif

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值