【模板】无符号压位高精度BigInterger

好了,过了几天终于把BASE从10拓展到了1e8,这样做的意义之一是让运算速度大大加快(尤其是乘法),而且打高精度除以高精度也变得有了意义,我就在这里贴代码,写点注意事项就好了。

首先还是外面的大框架

struct BigInterger
{
	static const int MAXNUM = 100000;
	static const int BASE = 1e8;
	static const int BIT = 8; 
	int num[MAXNUM], len; 
	BigInterger()
	{
		memset(num, 0, sizeof num);
		len = 0;
	}

}

可以看到,这里多了两个静态成员变量,BASE是基数,BIT是num数组一个元素的最大位数。

赋值(long long + string)

    BigInterger operator = (long long temp)
	{
		len = 0;
		do
		{
			num[++len] = temp % BASE;
			temp /= BASE;			
		}while (temp == 0);
		return *this;
	}
	BigInterger operator = (string &str)
	{
		len = 0;
		int i, j, temp;
		for (i = str.size() - 1;i >= BIT;i -= BIT)
		{
			temp = 0;
			for (j = BIT;j >= 1;j--)
				temp = temp * 10 + str[i - j + 1] - '0';
			num[++len] = temp;
		}
		temp = 0;
		for (j = 0;j <= i;j++)
			temp = temp * 10 + str[j] - '0';
		num[++len] = temp;
		return *this;
	}

long long版本没什么太大变化,string版本主要是每次拿BIT位(最后一次除外),然后用stringstream把string转换成int。看在stringstream很慢的份上,我把它去掉了。

输入输出(重载<<和>>运算符)

istream& operator >> (istream &in, BigInterger &temp)
{
	string str;
	in >> str;
	temp = str;
	return in;
}
ostream& operator << (ostream &out, const BigInterger &temp)
{
	char buf[BigInterger :: BIT];
	sprintf(buf, "%d", temp.num[temp.len]);
	out << buf;
	for (int i = temp.len - 1;i >= 1;i--)
	{
		sprintf(buf, "%08d", temp.num[i]);
		out << buf; 
	}
	return out;
}

可以看出,>>没有多大变化,<<则有些区别,sprintf到buf中,再输出。

去前导0clear

    void clear()
	{
		while (num[len] == 0 && len > 1)
			len--;
	}

关系运算符(<老大, 用小于号定义其他关系运算符)

    bool operator < (const BigInterger &cnt) const
	{
		if (len != cnt.len) return len < cnt.len;
		for (int i = len;i >= 1;i--)
			if (num[i] != cnt.num[i])
				return num[i] < cnt.num[i];
		return false;
	}
	bool operator > (const BigInterger &cnt) const { return cnt < *this; }
	bool operator <= (const BigInterger &cnt) const { return !(cnt < *this); }
	bool operator >= (const BigInterger &cnt) const { return !(*this < cnt); }
	bool operator != (const BigInterger &cnt) const { return cnt < *this || *this < cnt; }
	bool operator == (const BigInterger &cnt) const { return !(cnt < *this) && !(*this < cnt); }

四则运算部分

    BigInterger operator + (const BigInterger &cnt)
	{
		BigInterger ans;
		for (int i = 1, temp = 0;temp != 0 || i <= len || i <= cnt.len;i++)
		{
			temp += num[i] + cnt.num[i];
			ans.num[++ans.len] = temp % BASE;
			temp /= BASE;
		}
		return ans;
	}

基本没有变化,不解释了。

    BigInterger operator - (const BigInterger &cnt)
	{
		BigInterger ans;
		ans.len = len;
		for (int i = 0;i <= len;i++)
		{
			if (num[i] < cnt.num[i])
				num[i + 1]--, num[i] += BASE;
			ans.num[i] = num[i] - cnt.num[i];
		}
		ans.clear();
		return ans;
	}

也是基本没有变化,原来的借1当10变成借1当BASE罢了。

    BigInterger operator * (const BigInterger &cnt)
	{
		BigInterger ans;
		ans.len = len + cnt.len;
		for (int i = 1;i <= len;i++)
		{
			long long temp = 0;
			for (int j = 1;j <= cnt.len || temp != 0;j++)
			{
				temp += (long long)num[i] * cnt.num[j] + ans.num[i + j - 1];
				ans.num[i + j - 1] = temp % BASE;
				temp /= BASE;
			}
		}
		ans.clear();
		return ans;
	}

这儿就有些注意点了,首先,temp是long long类型,为什么我也不解释了,可以自己试着把long long改成int看看出了什么事,还有,temp运算时要进行强势类型转换,就是(long long)转换,否则temp结果会自动% INT_MAX,而且系统也不报错,就出了一些很是奇怪的答案。

除(高精度除以单精度)

    BigInterger operator / (const int &cnt)
	{
		BigInterger ans;
		ans.len = len;
		long long temp = 0;
		for (int i = len;i >= 1;i--)
		{	
			temp = temp * BASE + num[i]; 
			ans.num[i] = temp / cnt;
			temp %= cnt;
		}
		ans.clear();
		return ans;
	}
也没什么大区别,就是temp要是long long,不信改成int试试看就知道了。

猜你喜欢

转载自blog.csdn.net/diogenes_/article/details/79398518