在寻找一个有效的算法来乘以2个大数时,在论坛中遇到了以下c方法: -
...
typedef unsigned long long ULL;
ULL multiply (ULL a,ULL b)
{
ULL result = 0;
while(a > 0)
{
if(a & 1)
{
result += b;
}
a >>= 1;
b <<= 1;
}
return result;
}
...
上述算法不需要乘法指令,而只使用位移和加法运算(从而使其更快)。
检查方法是否正常,但是,我还没有完全了解它是如何工作的。解释会有所帮助。
答案 0 :(得分:4)
它迭代a
中的所有1位,添加b
移动了适当的数量。
首先请注意,如果a
为11001
,则可将其视为10000
+ 1000
+ 1
,因此a * b
为(10000*b) + (1000*b) + (1*b)
。
然后,请注意10000*b
只是b << 4
。
每次循环时,b
向左移动1以反映当前的移位量,a
向右移动1,以便可以测试低阶位。在此示例中,它最终会添加b
+ (b << 3)
+ (b << 4)
,这只是(1*b) + (1000*b) + (10000*b)
。
答案 1 :(得分:1)
123*
456=
6*(123)+
50*(123)+ //this means one digit shift, nice and easy
400*(123) //this means two digits shift, nice and easy
所以让我们做二进制文件:
101* //b
110= //a
0*(101)+
10*(101)+ //=1*(1010) //one digit shift
100*(101) //=1*(10100) //two digits shift
a 向右移动以访问其第一位: if(a&amp; 1)
b 向左移动每个位置进行与上面相同的一位移位
这正是我们手工繁殖时所做的事情
我建议使用
中的 uint64_t#include<stdint.h>
良好而清晰的编码风格:
#include<stdint.h>
uint64_t multiply(uint64_t a, uint64_t b)
{
uint64_t result = 0;
while (a > 0)
{
if (a & 1)
{
result += b;
}
a >>= 1;
b <<= 1;
}
return result;
}
int main() {
uint64_t a = 123;
uint64_t b = 456;
uint64_t c = multiply(a, b);
}