俄罗斯农名乘法

俄罗斯农名乘法适用于两个正整数相乘,只需要用到乘2、除2和加法操作。公式如下:
在这里插入图片描述
该乘法经常被用于两数相乘取模的场景,如果两数相乘已经超过数据范围,但取模后不会超过,我们就可以利用这个方法计算中间结果后取模,保证每次运算都在数据范围内。并且由于乘除2可以用移位来实现,因此非常适合计算机高效实现。
实现:

//递归实现
int ruM(int m, int n)
 {
 	if (m == 1)
 		return n;
 	if (m % 2)
 		return ruM((m - 1) / 2, 2 * n) + n;	//在这里进行取模,防止溢出
 	return ruM(m / 2, 2 * n);
} 

//迭代实现
int ruM2(int m, int n)
{
	int res = 0;
	while (m != 1)
	{
		if (m % 2)
		{
			res += n;	//在这里取模,防止溢出
			m = (m - 1) / 2;
			n *= 2;
		}
		else
		{
			m /= 2;
			n *= 2;
		}
	}
	
	return res + n;
}

//移位和加法。体现该方法真正的优势:使用移位代替乘除2。
int ruM3(int m, int n)
{
	int res = 0;
	while (m)
	{
		if (m & 1)
			res += n;	//在这里取模,防止溢出
		m >>= 1;	//移位代替乘除,更高效
		n <<= 1; 
	}
	
	return res; 
} 

这种拆分求和,防止溢出的思想,可以使用不同的乘除系数,比如可以对第一个乘数乘十,对第二个乘数除十,然后递归计算。当然这种情况下,就不能用移位来代替乘除,因此实现效率不高,下面是示例代码:

int mul(int a, int b)
{
	int res = 0;
	while (b)
	{
		if (b % 10)
			res += a * (b % 10);	//这这里取模,防止溢出
		a *= 10;	//普通乘除法,效率比移位低
		b /= 10;	
	}
	
	return res;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值