高精加&&高精乘

一. 题目背景

在日常计算中,加减乘除是最常见不过的,放到计算机中,在unsigned long long类型范围内,可以通过高级程序设计语言编译,传给计算机硬件,进行计算,但操作数要是很大的话,大于unsigned long long的范围,就是高精度数与高精度数的操作了。

二. 高精加和高精乘

初阶高精算法原理相当于小学学习的加减乘除,竖式加法乘法我们再熟悉不过了,例如123+789这个算式,用竖式写出来:

123
+789
81012
进位11
=912

答案为912,我们一步一步拆分看,先算了每一位的和,留下 mod 10 的结果,下一位加一( / 10)的结果,这也就是高精加算法的结晶了。

同理,高精乘我们小时候也用的是竖式算法,例如1234 * 56

1234
*56
6*6121824
5*5101520
516273824

第一步是将较小数放在下面,然后需要注意计算较小数第二位乘法时,起始位就是本位置,

下一步就是加起来每一位的和,进行与加法一样的套路,留下 mod 10 的结果,下一位加  / 10 .

t 516273824
t[-1]/101342
6193140
t%1069104
ans69104

答案为69104.

接下来就是对每一步的代码实现了.

三. 代码实现

初始录入数据

正常写数字是从高位开始,但我们的计算从个位开始,所以输入输出都是逆置的

首先输入接收的是两个字符串,定义变量

#define MAXN 100000010

char a[MAXN], b[MAXN];

int A[MAXN], B[MAXN];
int C[MAXN];

主函数中进行输入和逆置将 a[ ] 内字符转为 每一位数交给 A[ ].

    scanf("%s", a);
	scanf("%s", b);

	int sa = strlen(a);
	int sb = strlen(b);
	int maxsize = Max(sa, sb);

	for (int i = sa - 1, j = 0; i >= 0; j++, i--) A[j] = a[i] - '0';
	for (int i = sb - 1, j = 0; i >= 0; j++, i--) B[j] = b[i] - '0';

接下来就是算法的核心了

高精加:

加法函数代码:

void add(int A[],int sa, int B[],int sb,int C[]) {

	int sizec = Max(sa, sb);
	int t = 0;

	for (int i = 0; i < sizec; i++) {
		t += A[i] + B[i];
		C[i] = t % 10;
		t /= 10;
	}

	if (t) C[sizec] = t;
}

int Max(int a, int b) {
	if (a > b) return a;
	else return b;
}

注意当我们加至最后一位时,并没有把最后可能进位 t 放入答案数组,所以加上特判:

if (t) C[sizec] = t;

高精乘:

乘法函数代码:

void ride(int A[], int sa, int B[], int sb, int C[]) {
	int t = 0;
	if (sb > sa) return ride(B, sb, A, sa, C);

	for (int i = 0; i < sb; i++) {
		for (int j = 0; j < sa; j++) {
			C[i + j] += B[i] * A[j];
		}
	}

	for (int i = 0; i < sa + sb - 1; i++) {
		t += C[i];
		C[i] = t % 10;
		t = t / 10;
	}

	if (t) C[sa + sb - 1] = t;
}

因为必须让较小数作为竖式乘法的第二操作数,通过位数长度的比较返回正确的格式:

if (sb > sa) return ride(B, sb, A, sa, C);

乘法中最容易犯错的就是答案数组下标的遍历,较小数下标为 i ,计算每一位乘积时累加到 i + j 下标的答案数组中.

下一步的进位与加法相同,用 t 作为中间量,mod 10 和  /  10.

完整代码

高精加:

#include<stdio.h>
#include<string.h>

void add(int A[], int sa, int B[], int sb, int C[]);
int Max(int a, int b);

#define MAXN 100000010

char a[MAXN], b[MAXN];

int A[MAXN], B[MAXN];
int C[MAXN];

int main(void) {

	scanf("%s", a);
	scanf("%s", b);

	int sa = strlen(a);
	int sb = strlen(b);
	int maxsize = Max(sa, sb);

	for (int i = sa - 1, j = 0; i >= 0; j++, i--) A[j] = a[i] - '0';
	for (int i = sb - 1, j = 0; i >= 0; j++, i--) B[j] = b[i] - '0';

	add(A, sa, B, sb, C);

	if (C[maxsize]) printf("%d", C[maxsize]);
	for (int i = maxsize - 1; i >= 0; i--) printf("%d", C[i]);

	return 0;
}

void add(int A[],int sa, int B[],int sb,int C[]) {

	int sizec = Max(sa, sb);
	int t = 0;

	for (int i = 0; i < sizec; i++) {
		t += A[i] + B[i];
		C[i] = t % 10;
		t /= 10;
	}

	if (t) C[sizec] = t;
}

int Max(int a, int b) {
	if (a > b) return a;
	else return b;
}

高精乘:

#include<stdio.h>
#include<string.h>

#define MAXN 1000010

void ride(int A[], int sa, int B[], int sb, int C[]);

int  A[MAXN], B[MAXN], C[2 * MAXN];
char a[MAXN], b[MAXN];

int main(void) {
	scanf("%s", a);
	scanf("%s", b);

	if (a[0] == '0' || b[0] == '0') {
		printf("0");
		return 0;
	}

	int sa = strlen(a);
	int sb = strlen(b);
	
	for (int i = sa - 1, j = 0; i >= 0; i--, j++) A[j] = a[i] - '0';
	for (int i = sb - 1, j = 0; i >= 0; i--, j++) B[j] = b[i] - '0';

	ride(A, sa, B, sb, C);

	if (C[sa + sb - 1]) printf("%d", C[sa + sb - 1]);
	for (int i = sa + sb - 2; i >= 0; i--) printf("%d", C[i]);

	return 0;
}

void ride(int A[], int sa, int B[], int sb, int C[]) {
	int t = 0;
	if (sb > sa) return ride(B, sb, A, sa, C);

	for (int i = 0; i < sb; i++) {
		for (int j = 0; j < sa; j++) {
			C[i + j] += B[i] * A[j];
		}
	}

	for (int i = 0; i < sa + sb - 1; i++) {
		t += C[i];
		C[i] = t % 10;
		t = t / 10;
	}

	if (t) C[sa + sb - 1] = t;
}

最后一点注意,乘法若是有0,直接输出0就好啦.

学会了吗,学会了就来练习练习巩固模板吧

加:https://www.luogu.com.cn/problem/P1601

乘:https://www.luogu.com.cn/problem/P1303

本蒟蒻还会继续学习算法与大家分享,一起加油吧

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值