c++算法之500位的整数相乘

遇到这样一道算法题:

题目

计算两个非负整数 A,,B 的乘积,A,B 可能会很大;

输入

第一行输入一个非负整数 A。

第二行输入一个非负整数 B。

A,B 的长度不大于 500。

输出格式

输出A * B的值

分析:

题目的要求是两位500位以内的整数相乘,所以根据现有的数据类型,无法直接算出答案,需要另寻它径。初步分析,考虑最极限的情况,可以经过推理得到:比如2个两位数相乘产生的最大的数为4位;两个3位数相乘的最大结果为6位;两个4位数相乘的最大值是8位....;因此两位500位的数相乘之后所能产生的最大的数是1000位;因此,分析到这里,我们就需要用一个长度为1000的数组和两个长度为500得数组来保存结果和输入值。

此外,分析乘法的运算,之前已经提过,利用现有的数据类型无法直接得出答案。所以我们分析乘法的具体步骤。回想起之前学过的计算机组成原理的上机实验,在机器底层的加减乘除法,都是一位一位操作,然后通过位移的方式来循环判断,直至运算结束。所以这里我直接套路了之前的用法,用最原始的方法(就是笔算的方法),一位乘以一位的操作计算机可以帮我们完成。因此我们可以假设一波,比如计算:12344321 *  1999123,首先我们是用第二个数的末尾数字去乘第一个数,挨个乘每一位,遇到进位要加进位;也就是12344321 * 3,然后又是倒数第二个数乘以第一个数:12344321 * 1 ......;通过循环往复,最后把第二个数字的第一位乘以第一个数就完成了第一步。第二步,我们需要将之前乘法得到的数做加法,并且每次加法都要错位(其实也相当于位移一个了)。将所有得到的数相加完毕之后,我们就能得到我们想要的结果。先附上完整代码:


#include<iostream>
#include<stdlib.h>
#include<string>
int tmp[501] = { 0 };
using namespace std;
/*
此部分用来做乘法,也就是将乘数的某一位与被乘数整体相乘;
其步骤依然是一位一位乘;
参数分别是是被乘数,乘数的某一位,进位值;
*/
void mutiply(int a[], int bi, int pre)
{
	for (int i = 499; i >= 0; i--)
	{
		tmp[i + 1] = (a[i] * bi + pre) % 10;
		pre = (a[i] * bi + pre) / 10;
	}
}
/*
此部分做错位加法,上一步得到的值通过错位的方式与answer的相应位置相加;
参数分别是答案,答案下标;
其中局部变量indexTMP 代表tmp数组的下标;
pre代表进位值;
*/
void add(int answer[], int indexAnswer)
{
	int indexTMP = 500;
	int pre = 0;
	while (indexTMP >= 0)
	{
		int value = answer[indexAnswer] + tmp[indexTMP] + pre;
		answer[indexAnswer] = (answer[indexAnswer] + tmp[indexTMP] + pre) % 10;
		pre = value / 10;
		indexAnswer--;
		indexTMP--;
	}

}
/*
此部分调用以上两部分功能,通过循环来实现整体的乘法
参数分别是:被乘数,乘数,答案
*/
void function(int a[], int b[], int answer[])
{
	for (int i = 499; i >= 0; i--)
	{
		mutiply(a, b[i], 0);
		add(answer, i + 500);
	}
}
int main()
{
	string a;
	string b;
	string c;
	cin >> a;
	cin >> b;
	int a1[500] = { 0 };
	int b1[500] = { 0 };
	int answer[1000] = { 0 };
	int maxlength = a.length();
	int minlength = b.length();
	if (maxlength < minlength)
	{
		int tmp = minlength;
		minlength = maxlength;
		maxlength = tmp;
	}
    /*
    此部分是将字符串的数值转化到int型数组中
    */
	for (int i = a.length() - 1, j = 499; i >= 0; i--, j--)
	{
		a1[j] = a[i] - 48;
	}
	for (int i = b.length() - 1, j = 499; i >= 0; i--, j--)
	{
		b1[j] = b[i] - 48;
	}

	function(a1, b1, answer);
/*
不输出前面多余的0,从真正有意义的数值开始输出,index用来记录该下标
*/
	int index = 0;
	for (int i = 0; i <= 999; i++)
	{
		if (answer[i] != 0)
		{
			index=i;
			break;
		}

	}
	if(index!=0)
	{
		for (int k=index; k < 1000; k++)
		{
			cout << answer[k];
		}
	}
	else
	{
		cout << "0";
	}
	system("pause");
	return 0;
}

注意,本程序涉及全局变量tmp[501],改变量用来保存乘数的某一位乘以被乘数所得到的值,其最大为501位;此外,在function里,add方法的调用,第二个参数是i+500;这里保证了每一次相加时的错位,也就是相当于相加时tmp相对于answer整体左移一位,符合笔算的规则。

编译执行结果:

500位以内正整数随便乘,当然也可以改成正负数都可以,这里就不演示了,如有疑问欢迎评论区留言,欢迎大家转载! 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值