C++中高精度正整数运算代码模板

背景:

C++中有时我们会遇到(unsigned)long long也表示不了的大整数,这个时候我们常常会用高精度

为了简化使用过程以及模板化,我们不妨用struct或class来定义

详解:

框架:

template<int SIZE>//用来限制最大表示位数 
class bign(){
  private://在class外不能调用 
	int a[SIZE],len;//高精度整数,用数组表示 
  public:
	//一系列运算函数 
} 

输入输出:

    bign(){len=1;memset(a,0,sizeof(a));}//初始化
    void in(){
    	char s[SIZE];
    	scanf("%s",s);
	len=strlen(s);
	for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
	while(len>1&&a[len-1]==0) len--;//应对输入含前导0 
    }
    void out(bool Entr=true){//默认输出换行 
	for(int i=len-1;i>=0;i--) putchar(a[i]+'0');
	if(Entr) putchar('\n');
    }

赋值:

这部分主要是模拟实现,就不加注释了。相当于小学算数,自己思考一下

	void operator = (char *s){
		len=strlen(s);
		for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
		while(len>1&&a[len-1]==0) len--;
	}
	void operator = (int x){
		len=0;if(x==0) len=1,a[0]=0;
		while(x>0) a[len++]=x%10,x/=10;
	}
	void operator = (long long x){
		len=0;if(x==0) len=1,a[0]=0;
		while(x>0) a[len++]=x%10,x/=10;
	}

大小比较:

	friend bool operator < (bign a,bign b){
		if(a.len!=b.len) return a.len<b.len;
		for(int i=a.len-1;i>=0;i--)
			if(a.a[i]!=b.a[i]) return a.a[i]<b.a[i];
		return false;//表示a,b相等 
	}
	friend bool operator > (bign a,bign b){
		return b<a;
	}
	friend bool operator <= (bign a,bign b){
		return !(a>b);
	}
	friend bool operator >= (bign a,bign b){
		return !(a<b);
	}
	friend bool operator == (bign a,bign b){
		return !(a>b&&b<a);
	}
	friend bool operator != (bign a,bign b){
		return a<b||b<a;
	}

加减乘除运算:

	friend bign operator + (bign a,bign b){
		bign c;
		int lenth=max(a.len,b.len)+1;
		for(int i=0;i<lenth;i++) c.a[i]=a.a[i]+b.a[i];
		for(int i=0;i<lenth;i++){
			if(c.a[i]>9) c.a[i]-=10,c.a[i+1]++;
		}
		while(lenth>1&&c.a[lenth-1]==0) lenth--;
		c.len=lenth;
		return c;
	}
	friend bign operator - (bign a,bign b){//求a-b的绝对值 
		bign c;
		if(a<b) swap(a,b);
		int len=a.len;
		for(int i=0;i<len;i++)
			c.a[i]=a.a[i]-b.a[i];
		for(int i=0;i<len;i++)
			if(c.a[i]<0) c.a[i+1]--, c.a[i]+=10;
		while(len>1&&c.a[len-1]==0) len--;
		c.len=len;
		return c;
	}
	friend bign operator * (bign a,bign b){
		bign ans;
		int len=a.len+b.len;
		for(int i=0;i<a.len;i++)
			for(int j=0;j<b.len;j++)
				ans.a[i+j]+=a.a[i]*b.a[j];//这里要思考一下 
		for(int i=0;i<len;i++)
			if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
		while(len>1&&ans.a[len-1]==0) len--;
		ans.len=len;
		return ans;
	}
	friend bign operator * (bign a,int x){//防溢出,x<=200,000,000 
		bign ans;
		int len=a.len+20;
		for(int i=0;i<len;i++) ans.a[i]=a.a[i]*x;
		for(int i=0;i<len;i++)
			if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
		while(ans.a[len-1]==0&&len>1) len--;
		ans.len=len;
		return ans;
	}
	friend bign operator / (bign a,int b){//防溢出 
		bign c;
		int d=0,len=a.len;
		for(int i=len-1;i>=0;i--)
			d=d*10+a.a[i],c.a[i]=d/b,d=d%b;
		while(len>1&&c.a[len-1]==0) len--;
		c.len=len;
		return c;
	}
	friend bign operator / (bign a,bign b){
		bign c,d;
		int len=a.len;
		for(int i=len-1;i>=0;i--){
			d=d*10;
			d.a[0]=a.a[i];
			while(d>=b) c.a[i]++, d=d-b;//这里效率不是很高 
		}
		while(len>1&&c.a[len-1]==0) len--;
		c.len=len;
		return c;
	}

取模:

	friend int operator % (bign a,int b){//注意返回值为int 
		int d=0,len=a.len;
		for(int i=len-1;i>=0;i--)
			d=d*10+a.a[i],d=d%b;
		return d;
	}
	friend bign operator % (bign a,bign b){
		bign d;
		int len=a.len;
		for(int i=len-1;i>=0;i--){
			d=d*10;
			d.a[0]=a.a[i];
			while(d>=b) d=d-b;//同理,效率不够高 
		}
		while(len>1&&d.a[len-1]==0) len--;
		d.len=len;
		return d;
	}

部分扩展功能:

	friend bign gcd(bign a,bign b){//求最大公约数 
		bign zero;
		zero=0;
		return b==zero?a:gcd(b,a%b);
	}
	friend bign pow_mod(int a,int n,bign m){//求a^n mod m (m为高精度数) 
		bign ret,X;
		if(n==0){
			ret=1;return ret;
		}
		X=pow_mod(a,n/2,m);
		ret=(X*X)%m;
		if(n%2) ret=(ret*a)%m;
		return ret;
	}

完整代码:

template<int SIZE>
class bign{
  private:
	int a[SIZE],len;
  public:
	bign(){len=1;memset(a,0,sizeof(a));}
	void in(){
		char s[SIZE];
		scanf("%s",s);
		len=strlen(s);
		for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
		while(len>1&&a[len-1]==0) len--;
	}
	void out(bool Entr=true){
		for(int i=len-1;i>=0;i--) putchar(a[i]+'0');
		if(Entr) putchar('\n');
	}
	void operator = (char *s){
		len=strlen(s);
		for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
		while(len>1&&a[len-1]==0) len--;
	}
	void operator = (int x){
		len=0;if(x==0) len=1,a[0]=0;
		while(x>0) a[len++]=x%10,x/=10;
	}
	void operator = (long long x){
		len=0;if(x==0) len=1,a[0]=0;
		while(x>0) a[len++]=x%10,x/=10;
	}
	friend bool operator < (bign a,bign b){
		if(a.len!=b.len) return a.len<b.len;
		for(int i=a.len-1;i>=0;i--)
			if(a.a[i]!=b.a[i]) return a.a[i]<b.a[i];
		return false;
	}
	friend bool operator > (bign a,bign b){
		return b<a;
	}
	friend bool operator <= (bign a,bign b){
		return !(a>b);
	}
	friend bool operator >= (bign a,bign b){
		return !(a<b);
	}
	friend bool operator == (bign a,bign b){
		return !(a>b&&b<a);
	}
	friend bool operator != (bign a,bign b){
		return a<b||b<a;
	}
	friend bign operator + (bign a,bign b){
		bign c;
		int lenth=max(a.len,b.len)+1;
		for(int i=0;i<lenth;i++) c.a[i]=a.a[i]+b.a[i];
		for(int i=0;i<lenth;i++){
			if(c.a[i]>9) c.a[i]-=10,c.a[i+1]++;
		}
		while(lenth>1&&c.a[lenth-1]==0) lenth--;
		c.len=lenth;
		return c;
	}
	friend bign operator - (bign a,bign b){
		bign c;
		if(a<b) std::swap(a,b);
		int len=a.len;
		for(int i=0;i<len;i++)
			c.a[i]=a.a[i]-b.a[i];
		for(int i=0;i<len;i++)
			if(c.a[i]<0) c.a[i+1]--, c.a[i]+=10;
		while(len>1&&c.a[len-1]==0) len--;
		c.len=len;
		return c;
	}
	friend bign operator * (bign a,bign b){
		bign ans;
		int len=a.len+b.len;
		for(int i=0;i<a.len;i++)
			for(int j=0;j<b.len;j++)
				ans.a[i+j]+=a.a[i]*b.a[j];
		for(int i=0;i<len;i++)
			if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
		while(len>1&&ans.a[len-1]==0) len--;
		ans.len=len;
		return ans;
	}
	friend bign operator * (bign a,int x){
		bign ans;
		int len=a.len+20;
		for(int i=0;i<len;i++) ans.a[i]=a.a[i]*x;
		for(int i=0;i<len;i++)
			if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
		while(ans.a[len-1]==0&&len>1) len--;
		ans.len=len;
		return ans;
	}
	friend bign operator / (bign a,int b){
		bign c;
		int d=0,len=a.len;
		for(int i=len-1;i>=0;i--)
			d=d*10+a.a[i],c.a[i]=d/b,d=d%b;
		while(len>1&&c.a[len-1]==0) len--;
		c.len=len;
		return c;
	}
	friend bign operator / (bign a,bign b){
		bign c,d;
		int len=a.len;
		for(int i=len-1;i>=0;i--){
			d=d*10;
			d.a[0]=a.a[i];
			while(d>=b) c.a[i]++, d=d-b;
		}
		while(len>1&&c.a[len-1]==0) len--;
		c.len=len;
		return c;
	}
	friend int operator % (bign a,int b){
		int d=0,len=a.len;
		for(int i=len-1;i>=0;i--)
			d=d*10+a.a[i],d=d%b;
		return d;
	}
	friend bign operator % (bign a,bign b){
		bign d;
		int len=a.len;
		for(int i=len-1;i>=0;i--){
			d=d*10;
			d.a[0]=a.a[i];
			while(d>=b) d=d-b;
		}
		while(len>1&&d.a[len-1]==0) len--;
		d.len=len;
		return d;
	}
	friend bign gcd(bign a,bign b){
		bign zero;
		zero=0;
		return b==zero?a:gcd(b,a%b);
	}
	friend bign pow_mod(int a,int n,bign m){
		bign ret,X;
		if(n==0){
			ret=1;return ret;
		}
		X=pow_mod(a,n/2,m);
		ret=(X*X)%m;
		if(n%2) ret=(ret*a)%m;
		return ret;
	}
};


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现高精度运算的双向循环链表可以分为三个部分:节点结构体、链表结构体和高精度运算函数。 首先是节点结构体,可以定义如下: ```c++ struct Node { int val; // 当前节点的值 Node* next; // 指向下一个节点的指针 Node* prev; // 指向上一个节点的指针 // 构造函数 Node(int v = 0, Node* n = nullptr, Node* p = nullptr) : val(v), next(n), prev(p) {} }; ``` 接下来是链表结构体,可以定义如下: ```c++ struct LinkedList { Node* head; // 头指针 Node* tail; // 尾指针 // 构造函数 LinkedList() : head(nullptr), tail(nullptr) {} // 复制构造函数 LinkedList(const LinkedList& lst) { head = tail = nullptr; Node* p = lst.head; while (p != nullptr) { push_back(p->val); p = p->next; } } // 析构函数 ~LinkedList() { while (head != nullptr) { Node* p = head; head = head->next; delete p; } } // 在链表尾部插入一个节点 void push_back(int v) { Node* p = new Node(v, nullptr, tail); if (tail != nullptr) { tail->next = p; } else { head = p; } tail = p; } // 在链表头部插入一个节点 void push_front(int v) { Node* p = new Node(v, head, nullptr); if (head != nullptr) { head->prev = p; } else { tail = p; } head = p; } }; ``` 最后是高精度运算函数,可以实现加法、减法和乘法等运算: ```c++ // 高精度加法 LinkedList add(const LinkedList& a, const LinkedList& b) { LinkedList res; int carry = 0; // 进位 Node* p = a.tail; Node* q = b.tail; while (p != nullptr || q != nullptr) { int x = (p != nullptr) ? p->val : 0; int y = (q != nullptr) ? q->val : 0; int sum = x + y + carry; res.push_front(sum % 10); carry = sum / 10; if (p != nullptr) { p = p->prev; } if (q != nullptr) { q = q->prev; } } if (carry > 0) { res.push_front(carry); } return res; } // 高精度减法 LinkedList sub(const LinkedList& a, const LinkedList& b) { LinkedList res; int borrow = 0; // 借位 Node* p = a.tail; Node* q = b.tail; while (p != nullptr || q != nullptr) { int x = (p != nullptr) ? p->val : 0; int y = (q != nullptr) ? q->val : 0; int diff = x - y - borrow; if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } res.push_front(diff); if (p != nullptr) { p = p->prev; } if (q != nullptr) { q = q->prev; } } // 去除前导零 while (res.head->next != nullptr && res.head->val == 0) { Node* p = res.head; res.head = res.head->next; res.head->prev = nullptr; delete p; } return res; } // 高精度乘法 LinkedList mul(const LinkedList& a, const LinkedList& b) { LinkedList res; int n = a.tail != nullptr ? 1 : 0; int m = b.tail != nullptr ? 1 : 0; if (n == 0 || m == 0) { return res; } int len = n + m - 1; int* c = new int[len]; memset(c, 0, len * sizeof(int)); Node* p = a.tail; for (int i = 0; p != nullptr; i++, p = p->prev) { Node* q = b.tail; for (int j = 0; q != nullptr; j++, q = q->prev) { c[i + j] += p->val * q->val; c[i + j + 1] += c[i + j] / 10; c[i + j] %= 10; } } while (len > 0 && c[len - 1] == 0) { len--; } for (int i = len - 1; i >= 0; i--) { res.push_back(c[i]); } delete[] c; return res; } ``` 这样,我们就实现了一个可以进行高精度运算的双向循环链表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值