高精度计算_大整数_加_减_乘_除_大整数_基于deque_实现简洁

下面给出的通用大整数四则运算模板是实现简洁和执行效率的折中,  经测试该模板在本人的电脑上计算1000!在200毫秒左右, 应该能满足大部分OJ的要求, 如果仅仅需要大整数和普通的int类型进行四则运算, 那么请参考本人另一篇博客给出大整数与int数运算模板, 如果既希望进行大整数和大整数的运算又期望获得较高的执行效率(尤其是除法运算), 那么请参考本人另一篇博客中给出的基于vector的模板.

约定: 下面的代码中, a和b均为HEX进制数,a的位数 = a.size(),b的位数 = b.size(),a[0]和b[0]分别为a,b的最高位

const int HEX = 1e9;//运算采取的进制
deque<int> operator + (const deque<int> &a, const deque<int> &b){//返回a + b的结果
	deque<int> res;
	int carry = 0, len = max(a.size(), b.size());//carry:进位值 
	for(int i = 0, tmp; i < len; ++i)//当前计算结果的第i位		 
		tmp = (i < a.size()? a[a.size() - 1 - i]: 0) 
		     + (i < b.size()? b[b.size() - 1 - i]: 0) + carry
		, carry = tmp / HEX, res.push_front(tmp % HEX);
	if(carry) res.push_front(1);
	return res;
} 
deque<int> operator - (const deque<int> &a, const deque<int> &b){//返回a - b的结果,要求a >= b
	deque<int> res;
	for(int i = 0, rent = 0, tmp; i < a.size(); ++i)//计算a - b的结果的第i位, rent:借位值	
		tmp = a[a.size() - 1 - i] - (i < b.size()? b[b.size() - 1 - i]: 0) - rent
		, rent = (tmp < 0? 1: 0), res.push_front(tmp < 0? tmp + HEX: tmp); 
	while(res.size() > 1 && !res[0]) res.pop_front();//去除高位多余0 
	return res;
} 
deque<int> operator * (const deque<int> &a, const int b){//返回a * b(b为int型数,b < HEX)的结果
	deque<int> res;
	int carry = 0;
	for(long long i = a.size() - 1, tmp; i >= 0; --i)
		tmp = (long long)a[i] * b + carry
		, carry = tmp / HEX, res.push_front(tmp % HEX);
	if(carry) res.push_front(carry);
	while(res.size() > 1 && !res[0]) res.pop_front(); 
	return res;
} 
deque<int> operator * (const deque<int> &a, const deque<int> &b){//返回a * b的结果
	deque<int> res(1, 0), tmp;
	for(int i = b.size() - 1; i >= 0; --i)
		tmp = a * b[i], tmp.insert(tmp.end(), b.size() - 1 - i, 0)
		, res = res + tmp;
	return res;
} 
bool cmp(const deque<int> &a, const deque<int> &b){//若a <= b返回true,否则返回fasle
	return a.size() < b.size() || a.size() == b.size() && a <= b;
}
deque<int> operator / (const deque<int> &a, const deque<int> &b){//返回a / b的整数部分
	deque<int> res, rem(1, 0);
	for(int i = 0; i < a.size(); ++i){
		if(!rem[0]) rem.clear();
		rem.push_back(a[i]);		
		int begin = 0, len = 2, tmp;//使用基于倍增的试商方案
		while(tmp = begin + len - 1, len >= 2)
			if(tmp < HEX && cmp(b * (tmp), rem)) begin = tmp, len <<= 1; else len >>= 1;
		res.push_back(begin);
		rem = rem - (b * begin);
	}
	while(res.size() > 1 && !res[0]) res.pop_front(); 
	return res;
} 
void show(const deque<int> &num){//打印num表示的整数值 
	printf("%d", num[0]);
	for(int i = 1; i < num.size(); ++i) printf("%09d", num[i]);
}

下面的测试代码充分展示了上述模板使用方法:

//高精度大整数加,减,乘,除(基于deque_实现简洁)
#include <cstdio>
#include <deque>
#include <iostream>
#include<windows.h>
using namespace std;
const int HEX = 1e9;//运算采取的进制
deque<int> operator + (const deque<int> &a, const deque<int> &b){//返回a + b的结果
	deque<int> res;
	int carry = 0, len = max(a.size(), b.size());//carry:进位值 
	for(int i = 0, tmp; i < len; ++i)//当前计算结果的第i位		 
		tmp = (i < a.size()? a[a.size() - 1 - i]: 0) 
		     + (i < b.size()? b[b.size() - 1 - i]: 0) + carry
		, carry = tmp / HEX, res.push_front(tmp % HEX);
	if(carry) res.push_front(1);
	return res;
} 
deque<int> operator - (const deque<int> &a, const deque<int> &b){//返回a - b的结果,要求a >= b
	deque<int> res;
	for(int i = 0, rent = 0, tmp; i < a.size(); ++i)//计算a - b的结果的第i位, rent:借位值	
		tmp = a[a.size() - 1 - i] - (i < b.size()? b[b.size() - 1 - i]: 0) - rent
		, rent = (tmp < 0? 1: 0), res.push_front(tmp < 0? tmp + HEX: tmp); 
	while(res.size() > 1 && !res[0]) res.pop_front();//去除高位多余0 
	return res;
} 
deque<int> operator * (const deque<int> &a, const int b){//返回a * b(b为int型数,b < HEX)的结果
	deque<int> res;
	int carry = 0;
	for(long long i = a.size() - 1, tmp; i >= 0; --i)
		tmp = (long long)a[i] * b + carry
		, carry = tmp / HEX, res.push_front(tmp % HEX);
	if(carry) res.push_front(carry);
	while(res.size() > 1 && !res[0]) res.pop_front(); 
	return res;
} 
deque<int> operator * (const deque<int> &a, const deque<int> &b){//返回a * b的结果
	deque<int> res(1, 0), tmp;
	for(int i = b.size() - 1; i >= 0; --i)
		tmp = a * b[i], tmp.insert(tmp.end(), b.size() - 1 - i, 0)
		, res = res + tmp;
	return res;
} 
bool cmp(const deque<int> &a, const deque<int> &b){//若a <= b返回true,否则返回fasle
	return a.size() < b.size() || a.size() == b.size() && a <= b;
}
deque<int> operator / (const deque<int> &a, const deque<int> &b){//返回a / b的整数部分
	deque<int> res, rem(1, 0);
	for(int i = 0; i < a.size(); ++i){
		if(!rem[0]) rem.clear();
		rem.push_back(a[i]);		
		int begin = 0, len = 2, tmp;//使用基于倍增的试商方案
		while(tmp = begin + len - 1, len >= 2)
			if(tmp < HEX && cmp(b * (tmp), rem)) begin = tmp, len <<= 1; else len >>= 1;
		res.push_back(begin);
		rem = rem - (b * begin);
	}
	while(res.size() > 1 && !res[0]) res.pop_front(); 
	return res;
} 
void show(const deque<int> &num){//打印num表示的整数值 
	printf("%d", num[0]);
	for(int i = 1; i < num.size(); ++i) printf("%09d", num[i]);
}
int main(){
	//测试样例,计算1000!
	long long start = GetTickCount();
	deque<int> a(1, 1), tmp(1, 1), one(1, 1);
	for(int i = 1; i <= 1000; ++i) a = a * tmp, tmp = tmp + one;
	printf("Test case 1: 1000! = "), show(a), printf("\n");
	long long end = GetTickCount();
	cout << "1000!计算完成,用时" << (end - start) << "ms" << endl;
	tmp.clear(), tmp.push_back(1);
	deque<int> b(1, 1);
	for(int i = 1; i <= 996; ++i) b = b * tmp, tmp = tmp + one;
	printf("Test case 2: 1000! / 996! = "), show(a / b);
}

上述测试程序的运行截图(部分):

猜你喜欢

转载自blog.csdn.net/solider98/article/details/83217427
今日推荐