【C++】 正负整数大数运算模板

代码改自C++大数BigInt
原作者代码有部分问题,并且貌似不支持正负数(需要特判),这里改了一下,不用关心正负数问题了。
目前已经在acwing上验证了+ - * / %

#include<bits/stdc++.h>

using namespace std;
//数位长度
const int maxn = 1005;
/*
  改编自:https://blog.csdn.net/qq_44691917/article/details/107563699

  验证:
  + - *
  https://www.acwing.com/problem/content/3485/
  % /
  https://www.acwing.com/problem/content/4592/
 */
class BigInt {
    
    
private:
	void init() {
    
    
		//初始化为0
		len = 1;
		isPositive = true;
		memset(a, 0, sizeof a);
	}

	void initWithParameter(char* s) {
    
    
		init();
		//符号位放在isPositive标志位里面
		int bottom = 0;
		if (s[0] == '-') {
    
    
			isPositive = false;
			bottom = 1;
		}
		else {
    
    
			isPositive = true;
			bottom = 0;
		}

		len = strlen(s);
		int cnt = 0;
		for (int i = len - 1; i >= bottom; i--) a[cnt++] = s[i] - '0';
		len -= bottom;
	}
public:
	int a[maxn];//存储每一位数字
	int len;//数字部分长度,不包括符号位
	//判断正负(0看作正数)
	bool isPositive;
	//构造和输出
	BigInt() {
    
    
		init();
	}

	BigInt(char* s) {
    
    
		initWithParameter(s);
	}

	//注意需要从后向前存,运算时从前向后运算,输出时从后向前输出;低位存低位,高位存高位,便于进位。
	BigInt(string s) {
    
    
		initWithParameter((char*)s.c_str());
	}

	BigInt& operator = (const BigInt& T) {
    
      //重载赋值运算符,大数之间进行赋值运算
		len = T.len;
		isPositive = T.isPositive;
		memset(a, 0, sizeof(a));
		for (int i = 0; i < len; i++)
			a[i] = T.a[i];
		return *this;
	}

	void print() {
    
    
		if (!isPositive&&a[len-1]!=0) {
    
    
			printf("-");
		}
		for (int i = len - 1; i >= 0; i--) printf("%d", a[i]);
	}

	void println() {
    
    
		print();
		puts("");
	}


	//逻辑比较
	int operator > (const BigInt& T) const {
    
    
		int reverse = 0;//是否要反转结果
		//负数小于正数
		if (!isPositive && T.isPositive) {
    
    
			return 0;
		}
		else if (isPositive && !T.isPositive) {
    
    
			return 1;
		}
		else if (!isPositive && !T.isPositive) {
    
    
			//都是负数,结果相反:绝对值大的反而小
			reverse = 1;
		}//都是正数就正常运行
		if (len > T.len) return 1 - reverse;
		if (len < T.len) return reverse - 0;
		int cur = len - 1;
		while (a[cur] == T.a[cur] && cur >= 0) cur--;
		if (cur >= 0 && a[cur] > T.a[cur]) return 1 - reverse;
		else return reverse - 0;
	}

	int operator < (const BigInt& T) const {
    
    
		//逆操作
		int ans = (*this > T) ? 0 : 1;
		return ans;
	}

	int operator == (const BigInt& T) const {
    
    
		if (isPositive != T.isPositive) {
    
    
			return 0;
		}
		if (len != T.len) return 0;
		for (int i = len - 1; i >= 0; i--)
			if (a[i] != T.a[i]) return 0;
		return 1;
	}
	
	int operator != (const BigInt& T) const {
    
    
		return (*this==T)?0:1;
	}

	//求绝对值
	BigInt abs_B() {
    
    
		BigInt ret = *this;
		ret.isPositive = true;
		return ret;
	}

	//四则运算
	BigInt operator + (const BigInt& T) const {
    
    //已验证正确
		BigInt ret = T;
		//负数加负数
		if (!isPositive && !ret.isPositive) {
    
    
			ret.isPositive = false;
		}
		else if (isPositive && ret.isPositive) {
    
    //正数加正数
			ret.isPositive = true;
		}
		else {
    
    
			//有正有负,转换为正数减正数
			BigInt t1, t2;// t1正数,t2正数(原来是负数)
			if (isPositive)
			{
    
    
				t1 = *this, t2 = T;
			}
			else
			{
    
    
				t2 = *this, t1 = T;
			}
			// 都转换为正数
			t1.isPositive = true;
			t2.isPositive = true;

			//都看作绝对值相减
			ret = (t1 - t2);
			return ret;
		}

		int maxlen = len > T.len ? len : T.len; //取长度最长的那个
		for (int i = 0; i < maxlen; i++) {
    
    
			ret.a[i] += a[i];
			if (ret.a[i] >= 10) {
    
    
				ret.a[i + 1]++;
				ret.a[i] -= 10;
			}
		}
		//加号最多进一位
		ret.len = ret.a[maxlen] > 0 ? maxlen + 1 : maxlen;
		return ret;
	}

	BigInt operator - (const BigInt& T) const {
    
    //已验证正确
		//减法符号:大数减小数为正,否则为负
		BigInt t1 = *this, t2 = T, ret;//t1存比t2大的,ret存结果

		//正数减负数等于相加
		if (t1.isPositive && !t2.isPositive) {
    
    
			t1.isPositive = true;
			t2.isPositive = true;
			return t1 + t2;
		}
		else if (!t1.isPositive && t2.isPositive) {
    
    //负数减负数等于相加,结果符号取负
			t1.isPositive = true;
			t2.isPositive = true;
			ret = t1 + t2;
			ret.isPositive = false;
			return ret;
		}
		else {
    
    
			//正数减正数和负数减负数都要考虑大小来确定符号
			if (isPositive && T.isPositive) {
    
    
				//两个都是正数
				if (*this > T) {
    
     //取得最大数并标记是否为负
					t1 = *this, t2 = T;
					t1.isPositive = true;
				}
				else {
    
    
					t1 = T, t2 = *this;
					t1.isPositive = false;
				}
			}
			else {
    
    
				//两个都是负数,大的负数绝对值小,绝对值大的放前面t1,小的给t2
				if (*this > T) {
    
     //取得最大数并标记是否为负
					t2 = *this, t1 = T;
					t1.isPositive = true;
				}
				else {
    
    
					t2 = T, t1 = *this;
					t1.isPositive = false;
				}
			}
			//判断为结果符号后,都当作正数
		}


		int maxlen = max(t1.len, t2.len);
		for (int i = 0; i < maxlen; i++) {
    
    
			if (t1.a[i] < t2.a[i]) {
    
     //需要向前借位
				int j = i + 1;
				while (t1.a[j] == 0) j++;
				t1.a[j--]--;
				while (j > i) t1.a[j--] = 9;
				t1.a[i] += 10 - t2.a[i];
			}
			else t1.a[i] -= t2.a[i];
		}
		while (t1.a[maxlen - 1] == 0 && t1.len > 1) {
    
     //看看从最高位开始是否被借位变为0
			t1.len--;
			maxlen--;
		}
		return t1;
	}

	BigInt operator * (const BigInt& T) const {
    
    //已验证正确
		BigInt ret;

		if (!isPositive && !T.isPositive || isPositive && T.isPositive) {
    
    
			ret.isPositive = true;
		}
		else {
    
    
			ret.isPositive = false;
		}

		int i, j, temp1, temp2, up;
		for (i = 0; i < len; i++) {
    
    
			up = 0;
			for (j = 0; j < T.len; j++) {
    
    
				temp1 = a[i] * T.a[j] + ret.a[i + j] + up;
				if (temp1 >= 10) {
    
    
					temp2 = temp1 - temp1 / 10 * 10;
					up = temp1 / 10;
					ret.a[i + j] = temp2;
				}
				else {
    
    
					up = 0;
					ret.a[i + j] = temp1;
				}
			}
			if (up) ret.a[i + j] = up; //向最高位的进位是否存在
		}
		ret.len = len + T.len;
		while (ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--; //处理前导0
		return ret;
	}

	BigInt operator / (const long long& b) const {
    
    //已验证正确
		BigInt ret;
		//b!=0
		if (!isPositive && b < 0 || isPositive && b>0) {
    
    
			ret.isPositive = true;
		}
		else {
    
    
			ret.isPositive = false;
		}
		// a数组中不能有负数
		long long t_b = abs(b);
		
		long long down = 0;
		for (long long i = len - 1; i >= 0; i--) {
    
    
			ret.a[i] = (a[i] + down * 10) / t_b;
			down = a[i] + down * 10 - ret.a[i] * t_b;
		}
		ret.len = len;
		while (ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--;
		return ret;
	}

	//取模
	//取模的性质:(n+m)%p=((n%p)+m%p)%p
	//对每一位依次取模,并加上来自高位的余数乘以十
	long long operator % (const long long& b) const {
    
    //已验证正确
		long long ret = 0;
		for (long long i = len - 1; i >= 0; i--)
			ret = (ret * 10 + a[i]) % b;
		return ret;
	}

	//求幂
	//快速幂
	BigInt pow(int n) {
    
      //传入的n非负
		BigInt x = *this, ret("1");
		while (n) {
    
    
			if (n & 1) ret = ret * x;
			x = x * x;
			n >>= 1;
		}
		return ret;
	}
};


int main() {
    
    
	string s1, s2;
	cin >> s1 >> s2;
	BigInt b1(s1),b2(s2);


	至少这三个运算是对的
	//(b1 + b2).println();
	//(b1 - b2).println();
	//(b1 * b2).println();
	


	return 0;
}

其它的没验证,如有错误欢迎指出!

猜你喜欢

转载自blog.csdn.net/qq_33843237/article/details/128725389