大整数运算(必记)

21 篇文章 0 订阅
20 篇文章 1 订阅

大整数运算结构体

struct bign {
	int d[maxn];//d的低位就是数值N的低位
	int len;//大整数长度
	//int symbol;
	bign() {
		memset(d, 0, sizeof(d));
		len = 0;
		//symbol = 1;
	}
};

字符串转化为大整数型

bign str2bign(char str[]) {
	bign num;
	int len = strlen(str);
	if (str[0] == '-')num.symbol = -1;//如果是负数
	for (int i = 0; i < len; i++) {
		if (str[len - i - 1] == '-')continue;
		num.d[num.len] = str[len - i - 1] - '0';
		num.len++;
	}
	while (num.len > 1 && num.d[num.len - 1] == 0)num.len--;//消除前缀0
	return num;
}

大整数(绝对值)比较大小

int compare(bign x, bign y) {
	if (x.len > y.len)return 1; // 越长的数越大
	else if (x.len < y.len)return -1;
	else { // 相同长度,从高位开始向低位逐位比较
		for (int i = x.len - 1; i >= 0; i--) {
			if (x.d[i] > y.d[i])return 1;
			else if (x.d[i] < y.d[i])return -1;
		}
		return 0;
	}
}

加法(绝对值)

bign add(bign x, bign y) {
	bign z;
	int t, carry = 0;//t用来保存某位的运算,carry用来保存进位的大小
	for (int i = 0; i < x.len || i < y.len; i++) {
		t = x.d[i] + y.d[i] + carry;
		z.d[z.len++] = t % 10;
		carry = t / 10;
	}
	if (carry != 0)z.d[z.len++] = carry;//最后的进位
	return z;
}

减法(绝对值) |x|>|y|

bign sub(bign x, bign y) {
	bign z;
	for (int i = 0; i < x.len || i < y.len; i++) {
		if (x.d[i] < y.d[i]) { // 不够减
			x.d[i + 1] -= 1;//向高位借位
			x.d[i] += 10;
		}
		z.d[z.len++] = x.d[i] - y.d[i];
	}
	while (z.len > 1 && z.d[z.len - 1] == 0)z.len--;//消去高位多余的0
	return z;
}

低精度乘法(绝对值):

思想:x ✖️ y,假设x是bign类型,y是int类型,我们把x看作是由一个数组组成的数,而把y看作是一个整体

从低位开始遍历x数组每位的数x.d[i],令 t = x.d[i] * y,这样的话,t%10就是但前位的值,t/10就是进位的大小,我们用carry记录进位

那么高一位的运算过程就是 t = x.d[i]  * y + carry ,接着执行同样的步骤,取低位,把(进位)高位赋值到carry

bign multi(bign x, int y) {
	bign z;
	int carry = 0, t;
	for (int i = 0; i < x.len; i++) {
		t = x.d[i] * y + carry; //x的每位与y整体相乘
		z.d[z.len++] = t % 10; // 取低位为z但前位的值
		carry = t / 10; //取高位为进位
	}
	while (carry != 0) {
		z.d[z.len++] = carry % 10;
		carry /= 10;
	}
	return z;
}

低精度除法(绝对值):

把x看作是由一个数组组成的大整数,把y看作是一个整体,令r为余数(初始为0)

从x的高位开始遍历,对x的每一位x.d[i] ,都令新的余数为r = r*10+x.d[i]

与b位相对应的商= r / y ,更新余数r=r%y

// x/y
bign devide(bign x, int y, int &r) { //r 为余数
	bign z;
	r = 0;
	z.len = x.len;
	for (int i = x.len - 1; i >= 0; i--) { //从x的高位开始遍历
		r = r * 10 + x.d[i];//和上一位遗留的余数组合
		z.d[i] = r / y; //商
		r = r%y; // 取余
	}
	while (z.len > 1 && z.d[z.len - 1] == 0)z.len--;//消除前缀0
	return z;
}

带符号加法运算

		bign x = str2bign(str1);
		bign y = str2bign(str2);

		if (x.symbol * y.symbol > 0) { //如果两个数同号
			if (x.symbol == -1)printf("-"); //且都为负数
			print(add(x, y));
		}
		else if (x.symbol == 1 && y.symbol == -1) { //如果x>0,y<0
			if (compare(x, y) >= 0) { // |x|>=|y| ,那么x+y是正数
				print(sub(x, y));//绝对值相减,大的减去小的
			}
			else {// |x|<=|y| ,那么x+y是负数
				printf("-");
				print(sub(y, x));//绝对值相减,大的减去小的
			}
		}
		else {
			if (compare(x, y) <= 0) { //同理
				print(sub(y, x));
			}
			else {
				printf("-");
				print(sub(x, y));
			}
		}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值