大数的乘法和快速幂算法C语言描述

typedef struct bigint {
	unsigned arr[biglen] = { 0 };
	unsigned size = 0;
};

输入函数

bigint creat(char* key) {
	int len = strlen(key);
	bigint ret;
	ret.size = len;
	for (int i = 0; i < len; i++) {
		ret.arr[i] = key[len - 1 - i] - '0';
	}
	return ret;
}

输出函数

void big_output(const bigint& org) {
	int len = org.size;
	for (int k = len - 1; k >= 0; k--) {
		printf("%d", org.arr[k]);
	}
}

大数乘法:

根据我们乘法的步骤,在计算机上进行一个模拟即可;

如567 * 123 = (500 + 60 + 7)* 123 = 500 * 123 + 60 * 123 + 7 * 123;

这样就把大数乘以大数变成大数乘以小数再依次相加;

还有一些设计细节如将大数的所有位后移实现乘以10^k,这样每个大数都只需要乘以一个小于10的数再进行相应的后移即可。

当然,还有进位的基本方法也是需要用到的;

如下是乘法的例程:

bigint multi(bigint A, bigint B) {//大数的乘法
	bigint ret, tmp;
	for (int i = 0; i < B.size; i++) {//当前要乘的位(从低到高)
		if (B.arr[i] == 0) continue;
		copy(tmp, A);//拷贝A之后将它乘以B的某一位
		for (int j = 0; j < tmp.size; j++) {
				tmp.arr[j] *= B.arr[i];
		}
		push_back(tmp);//进位
		move_back(tmp, i);//乘以10^k
		ret = plus(ret, tmp);//答案加上这个组成部分
	}
	return ret;
}

它需要的前置函数:大家看代码直接懂

void push_back(bigint& Org) {//进位
	for (int k = 0; k < Org.size; k++) {
		Org.arr[k + 1] += Org.arr[k] / 10;
		Org.arr[k] = Org.arr[k] % 10;
		if (k == Org.size - 1 && Org.arr[k + 1] > 0) Org.size++;
	}
}
void move_back(bigint& Org, int times) {//后移times位实现乘以10^k
	while (times--){
		for (int k = Org.size; k > 0; k--) {
			Org.arr[k] = Org.arr[k - 1];
		}
		Org.arr[0] = 0;
		Org.size++;
	}
}
bigint plus(bigint A, bigint B) {//两个大数的加法
	bigint ret, tmp;
	if (A.size >= B.size) {//将较大的那个数作为加法的主体
		copy(ret, A);
		copy(tmp, B);
	}
	else {
		copy(ret, B);
		copy(tmp, A);
	}
	for (int k = 0; k < ret.size; k++) {
		ret.arr[k] += tmp.arr[k];//每一位从小到大依次相加
		push_back(ret);//进位
	}
	return ret;
}

这里提一下&表示引用即此时形参并非存储实参的值而是实参本身,函数可以在函数内直接改变实际参数的值,这是C++的内容但通过指针变量也能一样实现;

大数的快速幂:

快速幂算法:如A^11 = A^1 * A^2 * A^8;

通过将指数转化成二进制,然后通过创建一个不断自乘的中间量,在满足该位为1时将输出量乘以该中间量,最终达到进行 log n 次乘法实现指数运算的目的。

对于大整数快速幂还需要一个返回大整数余2的余数的函数和大整数不断除以二的函数,这里我们统一实现;

大数的快速幂算法如下:

bigint big_pow(bigint& X, bigint Y) {
	bigint ret, tmpX;
	ret.arr[0] = 1; ret.size = 1;
	copy(tmpX, X);
	while (Y.size != 0) {
		if (!Is2(Y)) {
			ret = multi(ret, tmpX);
		}
		tmpX = multi(tmpX, tmpX);
	}
	return ret;
}

前置函数:

bool Is2(bigint& org) {
	bool ret = 0;
	if (org.arr[0] % 2 == 0) ret = 1;
	org.arr[0] /= 2;
	for (int k = 1; k < org.size; k++) {
		if (org.arr[k] % 2 == 0) {
			org.arr[k] /= 2;
		}
		else {
			org.arr[k] /= 2;
			org.arr[k - 1] += 5;
		}
	}
	if (org.arr[org.size - 1] == 0) {
		org.size--;
	}
	return ret;
}

运行截图:

不过经过测试两个数中只能有一个数很大不然会超出堆栈。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值