Multiply two numbers without using * operator, and with minimum number of additions
例如:如果输入为5 * 8,则可以使用以下方法之一添加较大数量的较小次数,这将是答案。但是,如何最大限度地减少添加次数?
答案 0 :(得分:2)
最小化减少添加次数的一种策略是添加层次结构。这与经典功率算法中使用的策略相同,后者采用相同的技术来最小化乘法次数。
假设你需要
$rootScope.$on('$routeChangeSuccess', function(e, curr, prev) {
if (Object.getPrototypeOf($route.current) === $route.routes['/Home']) {
// do something when route changes to /Home
}
else if (Object.getPrototypeOf($route.current) === $route.routes['/About']) {
// do something when route changes to /About
}
}
计算M = a * 8 = a + a + a + a + a + a + a + a
后,您可以将其替换为上述添加内容并获取
m2 = a + a
然后您可以计算M = m2 + m2 + m2 + m2
并到达
m4 = m2 + m2
因此,结果是在M = m4 + m4
次添加而非原始3
中计算的。但是,向自身添加一个值可以替换为左移8
位(如果允许),这大大减少了添加次数。
这种技术可以通过分析其中一个被乘数的二进制表示来优雅地实现(正如它通常在幂算法中实现的那样)。例如。如果您需要计算1
,您可以这种方式进行计算
a * b
此类实现将使用的添加总数是int M = 0;
for (int m = a; b != 0; b >>= 1, m <<= 1)
if ((b & 1) != 0)
M += m;
中1
位的总数。它将b
乘以5
加1。
请注意,为了实现此策略提供的最低添加次数,将较大的数字乘以较小的数字不一定是最佳选择。例如。乘以8
使用的加法次数少于乘以8
。
答案 1 :(得分:1)
我喜欢Codor关于使用轮班和零添加的建议!
但是如果你真的只能使用加法而没有其他操作,如移位,日志,减法等,我相信计算a * b的最小数量将是:
min{int[log2(a+1)] + numbits(a), int[log2(b+1)] + numbits(b)} - 2
,其中
numbits(n)是二进制表示中的1的个数 整数n
int [x]是float x
的整数部分现在,我们是如何到达那里的?首先看看你的原始例子。您至少可以将添加内容组合在一起。例如。
8+8=16
16+16=32
32+8=40
为了概括这一点,如果你需要通过仅使用使用a的加法或已经计算的加法结果来乘以b次,你需要:
int [log2(b + 1)] - 添加1个以计算所需的所有2 ^ n.a中间数。
numbits(b)-1加法将所有中间结果加在一起,其中numbits(b)是b的二进制表示中的1的数目。
有趣的是,这意味着你的陈述
add the bigger number smaller number of times
并不总是减少添加次数的方法。
例如,如果你需要计算2 ^ 9 *(2 ^ 9 - 1),你最好计算基于(2 ^ 9-1)的增加而不是2 ^ 9,即使2 ^ 9更大。最快的方法是:
x = (2^9-1) + (2^9-1)
然后
x = x+x
总共9次添加8次。
如果您将2 ^ 9添加到自身,则需要8次添加才能首先获得所有2 ^ k * 2 ^ 9,然后再增加8次添加以将所有这些数字加在一起,总共添加16次。 / p>
答案 2 :(得分:1)
更好的例子是5 * 7
。这本质上是使用旧方法的二进制乘法,但巧妙地选择了乘数。
如果我们可以使用左移并且不算作加法:选择位数较小的数字作为乘数。在这种情况下,这将是5
。
111
x 101
------
111
000x <== This is not an addition, only a left shift
111xx
-------
100011 <== 2 additions totally.
-------
如果我们不能使用左移:请注意,左移与加倍/加法相同。然后我们将不得不使用略有不同的策略。由于被乘数将与(position of MSB - 1)
移位相同的次数,因此加法的数量将是具有较小值(position of MSB - 1) + (number of bits set)
的数字。如果是5 * 8
,则值分别为(3-1) + 2 = 4
和(4-1) = 3
。较小的是8
,因此将其用作乘数。
101
x 1000
-------
000
000x <== left shift
000xx <== left shift
101xxx <== left shift
--------
101000 <== no addition needed, so 3 additions totally.
--------
以上有三个班次和零添加。
答案 3 :(得分:0)
假设a与b相乘并且我们将结果存储在res中,我们只在b为奇数时才将res加到res中,否则将b除以2并将a乘以2.这是在循环中完成的b变为0.乘法和除法可以使用按位运算符完成。
让两个给定的数字为&#39; a&#39;和&#39; b&#39; 1)初始化结果&#39; res&#39;为0。 2)在&#39; b&#39;大于0 a)如果&#39; b&#39;是奇怪的,添加&#39; a&#39;到了&#39; res&#39; b)Double&#39; a&#39;和减半&#39; b&#39; 3)返回&#39; res&#39;。