非负数高精度

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_LEN = 1001, CARRY = 4, BASE = 10000;

struct BigInt
{
private:
	int A[MAX_LEN];
	int Len;

public:
	void Clear()
	{
		memset(A, 0, sizeof(A));
		Len = 0;
	}

	void Set(int x)
	{
		Clear();
		while (x)
		{
			A[Len++] = x%BASE;
			x /= BASE;
		}
		while (Len > 0 && !A[Len])
			Len--;//规定动作不要改
	}

	BigInt() { Clear(); }
	BigInt(int x) { Set(x); }


	void Read(char *s)
	{
		Clear();
		int cur = 0, pos = 0, pow = 1;
		for (int i = strlen(s) - 1; i >= 0; i--)//易忘点:倒序循环。因为位数小的数字在右边。//易忘点:-1
		{
			cur += (s[i] - '0')*pow;
			pow *= 10;//易忘点
			if (++pos == CARRY)
			{
				A[Len++] = cur;
				cur = pos = 0;
				pow = 1;
			}
		}
		if (!pos)//最好按照pos来判断。
			Len--;
		else
			A[Len] = cur;
	}

	void Read()
	{
		char s[MAX_LEN*CARRY];
		scanf("%s", s);
		Read(s);
	}

	void Print()
	{
		printf("%d", A[Len]);//易忘点。否则输出的数字前面多了几个0.
		for (int i = Len - 1; i >= 0; i--)
			printf("%0*d", CARRY, A[i]);//易忘点:%0*d。否则每一位前面的几个0没有输出。
		printf("\n");
	}


	BigInt operator = (const BigInt &a)
	{
		memcpy(A, a.A, sizeof(A));
		Len = a.Len;
		return *this;
	}

	bool operator < (const BigInt &a)
	{
		if (Len != a.Len)
			return Len < a.Len;
		for (int i = Len; i >= 0; i--)
			if (A[i] != a.A[i])
				return A[i] < a.A[i];
		return false;
	}


	BigInt operator += (const BigInt &a)
	{
		Len = max(Len, a.Len);
		for (int i = 0; i <= max(Len, a.Len); i++)
		{
			A[i] = (A[i] + a.A[i]);
			A[i + 1] += A[i] / BASE;//易忘点:不是(A[i]+a.A[i])/BASE,因为A[i]是修改后的值
			A[i] %= BASE;//易忘点:不要与第一句写在一起。//易忘点:此句和上一句/和%不要写反了
		}
		if (A[Len + 1])
			Len++;
		return *this;
	}

	BigInt operator + (const BigInt &a)
	{
		BigInt ans = *this;
		return ans += a;
	}


	BigInt operator -= (const BigInt &a)
	{
		for (int i = 0; i <= Len; i++)
		{
			A[i] -= a.A[i];
			if (A[i] < 0)
			{
				A[i] += BASE;
				A[i + 1]--;//易忘点:借位是-,不是+
			}
		}
		while (Len > 0 && !A[Len])//易忘点:Len>0
			Len--;
		return *this;
	}

	BigInt operator - (const BigInt &a)
	{
		BigInt ans = *this;
		return ans -= a;
	}


	BigInt operator *= (const BigInt &a)
	{
		BigInt b = *this;
		Clear();
		Len = a.Len + b.Len;//以上3句 易忘点:乘法不是在原有乘数的基础上修改出来的,而是一个全新的数字
		for (int i = 0; i <= a.Len; i++)
		{
			for (int j = 0; j <= b.Len; j++)
			{
				A[i + j] += a.A[i] * b.A[j];//易忘点:a. , b.//易忘点:+=,而不是=。相乘的结果最后是要累加的。
				A[i + j + 1] += A[i + j] / BASE;//易忘点:A[i+j],而不是a.A[i]*b.A[j]
				A[i + j] %= BASE;//易忘点:此句不可以与第一句结合在一起,因为第二句要用。
			}
		}
		if (A[Len + 1])
			Len++;
		return *this;
	}

	BigInt operator * (const BigInt &a)
	{
		BigInt ans = *this;
		return ans *= a;
	}


	BigInt operator /= (const int x)
	{
		for (int i = Len; i >= 0; i--)
		{
			if (i > 0)
				A[i - 1] += A[i] % x * BASE;
			A[i] /= x;//易忘点:此句并非在if的上面,否则if中的A[i]就是修改后的值了
		}
		while (Len > 0 && !A[Len])
		//while(A[0]>0&&A[Len]<=0)
			Len--;
		return *this;
	}

	BigInt operator / (const int x)
	{
		BigInt ans = *this;
		return ans /= x;
	}

	BigInt operator /= (const BigInt &a)
	{
		BigInt l, r = *this, one(1);//易忘点:r!=Len, l!=1(*this可能表示0)//易忘点:不能写one=1,因为声明时的=与重定义的=不是一个=
		while (l < r)
		{
			BigInt mid = (l + r + one) / 2;
			if (*this < (mid * a))//易忘点:<两边不要写反了,此判断说明当前的a选大了。
				r = mid - one;
			else
				l = mid;
		}
		return *this = l;
	}

	BigInt operator / (const BigInt &a)
	{
		BigInt ans = *this;
		return ans /= a;
	}

	bool IsZero()
	{
		return Len == 0 && A[0] == 0;
	}
};

  

posted @ 2018-04-19 20:04  headboy2002  阅读(108)  评论(0编辑  收藏  举报