全整数域的高精度类

 

包含以下内容:输入,输出,加法,减法,乘法,整除(除数为高精度),幂运算,模运算,运算带等号,由int、string赋值,六种大小比较
时间复杂度:
加法——O(n)
减法——O(n)
乘法——O(n^2)
除法——O(n^3)
取模——O(n^3)

若有各种优化建议或者发现了bug,欢迎随时评论留言~

// BigNum.h

#ifndef _BigNum_h
#define _BigNum_h

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class BigNum
{
	friend BigNum operator+(const BigNum a, const BigNum b);
	friend BigNum operator+=(BigNum &a, const BigNum b);
	friend BigNum operator-(BigNum a);
	friend BigNum operator-(BigNum a, BigNum b);
	friend BigNum operator-=(BigNum &a, const BigNum b);
	friend BigNum operator*(const BigNum a, const BigNum b);
	friend BigNum operator*=(BigNum &a, const BigNum b);
	friend BigNum operator/(const BigNum a, BigNum b);
	friend BigNum operator/=(BigNum &a, const BigNum b);
	friend BigNum operator%(const BigNum a, BigNum b);
	friend BigNum operator%=(BigNum &a, const BigNum b);
	friend BigNum operator^(const BigNum a, BigNum b);
	friend BigNum operator++(BigNum a);
	friend BigNum operator++(BigNum &a, int n);
	friend BigNum operator--(BigNum a);
	friend BigNum operator--(BigNum &a, int n);
	friend bool operator<(const BigNum a, const BigNum b);
	friend bool operator>(const BigNum a, const BigNum b);
	friend bool operator==(const BigNum a, const BigNum b);
	friend bool operator<=(const BigNum a, const BigNum b);
	friend bool operator>=(const BigNum a, const BigNum b);
	friend bool operator!=(const BigNum a, const BigNum b);
	friend ostream &operator<<(ostream &os, const BigNum &n);
	friend istream &operator>>(istream &is, BigNum &n);
protected:
	bool symbol; // 表示正负号,false为正,true为负
	vector <int> num;
public:
	// 运用赋值号初始化
	BigNum(const int n = 0) { *this = n; }
	BigNum(const string n) { *this = n; }

	BigNum &operator=(const int &n);
	BigNum &operator=(const string &n);
	BigNum &operator=(const BigNum &n);
};

BigNum &BigNum::operator=(const int &n)
{
	int temp;

	num.erase(num.begin(), num.end()); // 数据清空
	// 确定符号,并将数变为正
	if (n < 0)
	{
		symbol = true;
		temp = -n;
	}
	else
	{
		symbol = false;
		temp = n;
	}
	// 开始填入数值
	while (temp >= 10)
	{
		num.push_back(temp % 10);
		temp /= 10;
	}
	num.push_back(temp);
	// int没有前置0,所以不用去除

	return *this;
}

BigNum &BigNum::operator=(const string &n)
{
	num.erase(num.begin(), num.end()); // 数据清空
	// 填入除首位以外的数
	for (string::size_type i(n.size() - 1); i>0; i--)
		num.push_back(n[i] - '0');
	// 判断符号
	if (n[0] == '-') symbol = true;
	else
	{
		symbol = false;
		num.push_back(n[0] - '0');
	}
	// 去除前置0并确保至少留一位
	for (vector <int>::size_type i(num.size() - 1); num[i] == 0 && i>0; i--)
		num.pop_back();

	return *this;
}

BigNum &BigNum::operator=(const BigNum &n)
{
	num.erase(num.begin(), num.end()); // 数据清空
	symbol = n.symbol;
	for (vector <int>::size_type i(0); i<n.num.size(); i++)
		num.push_back(n.num[i]);

	return *this;
}

ostream &operator<<(ostream &os, const BigNum &n)
{
	if (n.symbol == true) os << '-';
	for (vector <int>::size_type i(n.num.size() - 1); i>0; i--)
		os << n.num[i];
	os << n.num[0]; // 为防止出错,最后一位单独输出

	return os;
}

istream &operator>>(istream &is, BigNum &n)
{
	string temp;
	is >> temp;
	n = temp;

	return is;
}

BigNum operator+(const BigNum a, const BigNum b)
{
	BigNum c;

	// 先确定符号,同号相加,异号相减
	if (a.symbol == b.symbol) c.symbol = a.symbol;
	else if (a.symbol)
		return b - (-a);
	else
		return a - (-b);

	vector <int>::size_type lenA(a.num.size()), lenB(b.num.size()), lenC;
	lenC = (lenA > lenB ? lenA : lenB);

	for (vector <int>::size_type i(0); i<lenC; i++)
	{
		int temp(c.num[c.num.size() - 1]); // 取出末尾的数
		if (i < lenA) temp += a.num[i];
		if (i < lenB) temp += b.num[i];
		c.num[c.num.size() - 1] = temp % 10;
		c.num.push_back(temp / 10); // 进位
	}
	if (c.num[lenC] == 0) c.num.pop_back(); // 若最后没有进位,则舍弃前置0

	return c;
}

BigNum operator+=(BigNum &a, const BigNum b)
{
	a = a + b;
	return a;
}

BigNum operator-(BigNum a)
{
	if (a != 0) a.symbol = !a.symbol; // 变为负数,注意0的符号
	return a;
}

BigNum operator-(BigNum a, BigNum b)
{
	BigNum c, big, small;

	// 先确定符号
	if (a < b) c.symbol = true;
	else c.symbol = false;
	if (a.symbol == b.symbol) // 同号绝对值相减
	{
		a.symbol = b.symbol = false;
		if (a < b)
		{
			small = a; big = b;
		}
		else
		{
			small = b; big = a;
		}

		vector <int>::size_type lon(big.num.size()), sho(small.num.size()), len;
		
		for (vector <int>::size_type i(0); i<lon; i++)
		{
			int temp(c.num[c.num.size() - 1] + 10);
			if (i < sho) temp += (big.num[i] - small.num[i]);
			else temp += big.num[i];
			c.num[c.num.size() - 1] = temp % 10;
			c.num.push_back(temp / 10 - 1);
		}
		// 去除前置0
		len = c.num.size();
		while (len--)
		{
			if (c.num[len] == 0) c.num.pop_back();
			else break;
		}
		if (c.num.empty()) c.num.push_back(0); // 确保至少留一位
	}
	else // 异号绝对值相加
	{
		a.symbol = b.symbol = false;
		c.num = (a + b).num;
	}

	return c;
}

BigNum operator-=(BigNum &a, const BigNum b)
{
	a = a - b;
	return a;
}

BigNum operator*(const BigNum a, const BigNum b)
{
	BigNum c;
	vector <int>::size_type lenA(a.num.size()), lenB(b.num.size()), len(lenA + lenB - 1);

	c.num.insert(c.num.begin(), len, 0); // 初始化0
	for (vector <int>::size_type i(0); i<lenA; i++)
	{
		for (vector <int>::size_type j(0); j<lenB; j++)
		{
			c.num[i + j] += a.num[i] * b.num[j];
			c.num[i + j + 1] += c.num[i + j] / 10;
			c.num[i +j] %= 10;
		}
	}
	if (c.num[len] == 0) c.num.pop_back();
	if (c != 0) c.symbol = a.symbol ^ b.symbol; // 同假异真

	return c;
}

BigNum operator*=(BigNum &a, const BigNum b)
{
	a = a * b;
	return a;
}

BigNum operator/(const BigNum a, BigNum b)
{
	if (b == 0 || a == 0) return 0; // 除数为0的情况
	BigNum temp1, temp2;
	bool flag = a.symbol ^ b.symbol; // 暂存符号
	b.symbol = false;
	string s(a.num.size(), '0'); // 存放商
	vector <int>::size_type i(a.num.size());
	string::size_type j(0);

	while (i--)
	{
		if (temp1 == 0) temp1.num.pop_back();
		temp1.num.insert(temp1.num.begin(), a.num[i]); // 往后取一位
		int k(10); // 试商
		while (k--)
		{
			temp2 = temp1 - b * k;
			if (temp2 >= 0)
			{
				s[j] += k;
				temp1 = temp2; // 保留余数
				break;
			}
		}
		j++;
	}

	BigNum c(s); // 构造函数自动去除前置0
	c.symbol = flag; // 归还符号
	return c;
}

BigNum operator/=(BigNum &a, const BigNum b)
{
	a = a / b;
	return a;
}

BigNum operator%(const BigNum a, BigNum b)
{
	if (b == 0 || a == 0) return 0;
	BigNum c, temp;
	b.symbol = false;
	vector <int>::size_type i(a.num.size());

	while (i--)
	{
		if (c == 0) c.num.pop_back();
		c.num.insert(c.num.begin(), a.num[i]);
		int k(10);
		while (k--)
		{
			temp = c - b * k;
			if (temp >= 0)
			{
				c = temp; // c就是余数
				break;
			}
		}
	}
	c.symbol = a.symbol;
	return c;
}

BigNum operator%=(BigNum &a, const BigNum b)
{
	a = a % b;
	return a;
}

BigNum operator^(const BigNum a, BigNum b) // 快速幂运算
{
	BigNum c = 1, base = a;

	while (b != 0)
	{
		if (b.num[0] % 2) c *= base;
		base *= base; b /= 2;
	}

	return c;
}

BigNum operator++(BigNum a)
{
	a = a + 1;
	return a;
}

BigNum operator++(BigNum &a, int n)
{
	BigNum b = a;
	a = a + 1;
	return b;
}

BigNum operator--(BigNum a)
{
	a = a - 1;
	return a;
}

BigNum operator--(BigNum &a, int n)
{
	BigNum b = a;
	a = a - 1;
	return b;
}

bool operator<(const BigNum a, const BigNum b)
{
	vector <int>::size_type lenA(a.num.size()), lenB(b.num.size());

	if (a.symbol && !b.symbol) return true; // a负b正
	if (!a.symbol && b.symbol) return false; // a正b负
	if (lenA != lenB) // 长度不相等
	{
		if (!a.symbol) return lenA < lenB;
		else return lenA > lenB;
	}
	for (vector <int>::size_type i(lenA - 1); i>0; i--)
	{
		if (a.num[i] != b.num[i])
		{
			if (!a.symbol) return a.num[i] < b.num[i];
			else return a.num[i] > b.num[i];
		}
	}
	if (!a.symbol) return a.num[0] < b.num[0];
	else return a.num[0] > b.num[0];
}

bool operator>(const BigNum a, const BigNum b)
{
	return b < a;
}

bool operator==(const BigNum a, const BigNum b)
{
	return !(a != b);
}

bool operator<=(const BigNum a, const BigNum b)
{
	return !(a > b);
}

bool operator>=(const BigNum a, const BigNum b)
{
	return !(a < b);
}

bool operator!=(const BigNum a, const BigNum b)
{
	return (a < b || a > b);
}

#endif

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值