大整数乘法

时间:2014.04.19

地点:基地二楼

-------------------------------------------------------------------------

一、大数乘法应用背景

  某些应用,需要对超过100位的十进制整数进行乘法运算,比如在密码技术当中,这样因为整数过于的长,计算机的一个字也装不下这样的长度整数,于是要做特别的处理,况且乘法的效率上也想要有所提高。显然我们通常的笔算乘法时间复杂度为平方级别的。我们想构建一个小于平方级别的算法。

-------------------------------------------------------------------------

二、大数乘法基本原理

  先看一个两位数的乘法例子:23*14

23=2*10^1+3*10^0;

14=1*10^1+4*10^0;

23*14=(2*1)10^2+(2*1+3*4)10^1+(3*4)10^0

在这里2*1和3*4是不可避免的,然后利用它们两我们使用一次乘法就可计算出中间值。现在我们来总结一条规律:

对于任何两位数a=a1a0和b=b1b0,它们的乘积c可以这样计算:

c=ab=c2  * 10^2  + c1 * 10^1  +c0

其中 c2=a1*b1  c0=a0 *b0     c1=(a1+a0)(b1+b0)-(c2+c0)

现在,假设有两个n位整数a和b,如果没有,我们就根据最长的补齐n位数,且假设n为偶数,我们可以把数一分为二,把a的前半部分记为a1,后半部分记为a0,对b也做类似的处理,前半部分叫b1,后半部分叫b0。于是有:

a=a1 * 10^(n/2) +a0                        b=b1 * 10^(n/2) + b0

那么和处理两位数一样,我们可以类似的得到:

c=ab=c2 * 10^n  + c1  * 1 0^ (n/2)  +c0

其中,c2=a1*b1     c0=a0*b0    c1=(a1+a0)(b1+b0)-(c2+c0)

即中间部分是a的两部分和与b的两部分和的积减去c2与c0的和。

-------------------------------------------------------------------------

三、大数乘法的实现

  在大数乘法的实现中,一是要注意n必须为偶数,当然如果n是2的幂,那么狠好办,一直递归下去,直到n=1时直接返回值,但很多时候,这样做很浪费,我们只要每次递归检查数的位数然后补齐为偶数位即可。还有一个小问题是在获得数据的位数时,刚开始我是用除10的方法得到的,在一个while循环里,但某次检查我发现程序出错,原因是当到了传进去的数字为0时,它不会返回的数位为0,找这个错找了好久,数字o的位数应该是为1,所以修改后应该在一个do...while循环中进行。源码如下:

#include<iostream>
using namespace std;
int IntegerLength(long long data)
{
	int size = 0;
	do
	{
		data /= 10;
		++size;
	} while (data);
	return size;
}
long long BigDataMultiply(long long a, long long b)
{
	size_t a_length, b_length;
	a_length = IntegerLength(a);
	b_length = IntegerLength(b);
	size_t size = (a_length >= b_length) ? a_length : b_length;
	if (size == 1)
		return a*b;
	else
	{
		if (size % 2 != 0)
			size += 1;
		long long partion_data = static_cast<int>(pow(10, size / 2));
		long long a1 = a / partion_data;
		long long b1 = b / partion_data;
		long long a0 = a%partion_data;
		long long b0 = b%partion_data;
		long long c2 = BigDataMultiply(a1, b1);
		long long c0 = BigDataMultiply(a0, b0);
		long long c1 = BigDataMultiply((a1 + a0),(b1 + b0)) - (c2 + c0);
		long long c = c2*partion_data*partion_data + c1*partion_data + c0;
		return c;
	}
}
int main()
{
	long long a, b;
	cin >> a >> b;
	cout << BigDataMultiply(a, b) << endl;
	return EXIT_SUCCESS;
}

-------------------------------------------------------------------------

四、性能分析

  这个算法相比笔算法的平方级时间复杂度已经下降到n的1.585,已经得到了很大的改进。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值