最近刷题,总遇到大数加法(浮点数)和乘法问题(阶乘),总结一下思路。
大数乘法
主要思想:编程实现竖式乘法(小学时候学的列竖式计算乘法)
- 创建一个很大的数组,用于存储大数的每一位。(注意这里数组的下标是逆序的逻辑。)
- 外层循环用于从1开始递增到n。
- 内层循环分为两部分,
其一:模拟竖式乘法;
其二:处理进位 - 循环输出数组的大数。
#include <stdio.h>
int main() {
int n, i ,j;
while(scanf("%d",&n) != EOF){
int last = 1; //保存大数的位数
int a[100000] = {0,1,0};
//保存大数 数组是倒序存储的,即n-1,n-2,...,3,2,1,0 其中下标为0处不存数,存放0
for (int i = 1; i <= n; i++){
//将大数的每一位都与当前的i阶相乘,并将结果存在当前大数的下标空间下,即此时不处理进位 ->模拟竖式乘法
for (int j = 1; j <= last; j++){
a[j] *= i;
}
//处理进位
/*j <= last 保证结果是>=大数的位数的。
a[j] != 0避免结果位数<大数位数时,a[j]出现0的情况导致退出计算 。*/
for(j = 1; j <= last || a[j] != 0; j++){
a[j+1] += a[j] /10; //如果有进位直接就可以在下一个数组空间中,写入进位
a[j] %= 10;
}
last = j-1;//更新位数
}
//输出阶乘结果
for (j = last; j >= 1; j--)
printf("%d", a[j]);
printf("\n");
}
}
推荐B站的【大数乘法-40的阶乘-40!-详细解析-哔哩哔哩】 https://b23.tv/ZXkcmuj 讲的很详细,我是看这位up的讲解才懂的。
大数加法
思想类似于上述的大数乘法。(下面的方法最多只能计算到10位的数据,下次实现一下转成字符数组的形式,可以计算更多位数)
下面分步骤进行代码演示,最后给出完整代码。
- 大数的每一位都相加,并将结果存在当前大数的下标空间下,即此时不处理进位 ->模拟竖式加法
注意,数组的逻辑是逆序的,即数组中存放数据的位次为:个位、十位、百位…以此类推。
- 处理进位
- 输出结果
完整代码
#include <stdio.h>
int main() {
int m,n, i ,j;
int last; //保存大数的位数
int a[11] = {0}; //保存大数 数组是倒序存储的,即n-1,n-2,...,3,2,1,0 其中下标为0处不存数,存放0
long int aaa = 1234567891; //最多只能到10位
printf("enter two number:\n");
scanf("%d",&m);
scanf("%d",&n);
//将大数的每一位都相加,并将结果存在当前大数的下标空间下,即此时不处理进位 ->模拟竖式加法
for (int j = 1; j <= 10; j++){
a[j] = (m%10) + (n%10);
m = m/10;
n = n/10;
}
//处理进位
/*j <= last 保证结果是>=大数的位数的。
a[j] != 0避免结果位数<大数位数时,a[j]出现0的情况导致退出计算 。*/
for(j = 1; j <= 10 || a[j] != 0; j++){
a[j+1] += a[j] /10; //如果有进位直接就可以在下一个数组空间中,写入进位
a[j] %= 10;
}
last = j-1;//更新位数
//输出结果
for (j = last; j >= 1; j--)
printf("%d", a[j]);
printf("\n");
}