高精度乘法
问题描述
题目描述
给出两个长度小于 100 位的正整数,求其乘积。
输入描述
两行,一行一个数。
输出描述
一行,为所求乘积。
样例输入
1937
2931
样例输出
5677347
问题分析
-
考虑到输入范围会超过
int
类型的范围,使用字符串来接收输入数据,同时两数的乘积不超过200
位,同样超过int
类型的范围,应该使用数组存放乘积的结果。 -
在接收输入数据后应考虑改为
int
类型的数组存储输入数据,每个元素代表整数的每一位,下标0
代表个位,下标1
代表十位,依此类推。 -
加下来就是计算两个大整数相乘,通过两重循环逐位计算被乘数和乘数的每一位,将乘积加入到结果数组的对应位置中,并对进位进行处理。
-
最后就是对结果数组进行逆序输出。
代码实现
字符串转换为整数
-
目的:将字符串形式的数字转化为整数数组的形式
-
参数:strNum,原始字符串;num,转换后的整数数组;sz,原始字符串的长度
void toNum(char* strNum, int* num, int sz)
{
int i = 0;
int j = sz - 1;
// 将字符串逆序转化为整数数组
for (i = 0; i < sz; i++, j--)
{
num[i] = strNum[j] - '0';// 将字符型数字转换为整型数字
}
}
计算乘积
-
目的:两个大整数相乘并返回结果数组的有效长度
-
参数:num1,被乘数的整数数组;num2,乘数的整数数组; ret,存储结果的整数数组;sz1、sz2,两个大整数的位数
int multi(int* num1, int* num2, int* ret,int sz1,int sz2)
{
int i = 0;
int carry = 0;//进位
int location = 0;//结果数组中的下标
//逐位相乘,并将结果加入到对应的位置中
for (i = 0; i < sz1; i++)
{
int j = 0;
location = i;//每次相乘结果从第i位相加
for (j = 0; j < sz2; j++)
{
int temp = num2[j] * num1[i] + carry;//当前位的乘积加上进位
ret[location] += temp % 10;
if (ret[location] >= 10)//处理进位
{
carry = temp / 10 + ret[location] / 10;
ret[location] %= 10;//更新当前位的值
}
else
{
carry = temp / 10;
}
location++;//移动到下一位
}
//处理剩余的进位
while (carry)
{
ret[location++] += carry % 10;
carry /= 10;
}
}
return location;//返回结果数组的有效值
}
输出结果
-
目的:将相乘后的整数数组以十进制形式输出到屏幕上
-
参数:ret,存储结果的整数数组;sz,结果数组的长度
void printNum(int* ret, int sz)
{
int i = 0;
// 逆序输出数组中的每个元素
for (i = sz - 1; i > -1; i--)
{
printf("%d", ret[i]);
}
printf("\n");
}
main函数
int main()
{
//用字符串读取输入的数字
char strNum1[100] = { 0 };
char strNum2[100] = { 0 };
while (scanf("%s %s", strNum1, strNum2) != EOF)
{
int sz1 = strlen(strNum1);
int sz2 = strlen(strNum2);
int num1[100] = { 0 };
int num2[100] = { 0 };
int ret[201] = { 0 };//结果数组
//转换字符串到整型数组
toNum(strNum1, num1, sz1);
toNum(strNum2, num2, sz2);
//计算乘积
int location = multi(num1, num2, ret, sz1, sz2);
//输出
printNum(ret, location);
}
return 0;
}
头文件
#include <stdio.h>
#include <string.h>