这个分治策略可行么,高手指点一二,谢先!
我想用分治策略实现计算两个大数的乘积,可行么?
//
// —————— ——————
// x = |___|___| y = |___|___|
// n/2 n/2 n/2 n/2
//
// 图1 大整数X和Y的分段
//
// 我们将n位的二进制整数X和Y各分为2段,每段的长为n/2位(为简单起见,假设n是2的幂),
// 如图1所示。
// 由此,X=A2n/2+B ,Y=C2n/2+D。这样,X和Y的乘积为:
//
// XY=(A2n/2+B)(C2n/2+D)=AC2n+(AD+CB)2n/2+BD (1)
//
// 如果按式(1)计算XY,则我们必须进行4次n/2位整数的乘法(AC,AD,BC和BD),
// 以及3次不超过n位的整数加法(分别对应于式(1)中的加号),此外还要做2次移位
// (分别对应于式(1)中乘2n和乘2n/2)。所有这些加法和移位共用O(n)步运算。
// 设T(n)是2个n位整数相乘所需的运算总数,则由式(1),我们有:
//
// _
// | T(1) = 1
// | (2)
// |_T(n) = 4T(n/2) + O(n)
//
// 由此可得T(n)=O(n2)。因此,用(1)式来计算X和Y的乘积并不比小学生的方法更有效。
// 要想改进算法的计算复杂性,必须减少乘法次数。为此我们把XY写成另一种形式:
//
// XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD (3)
//
// 虽然,式(3)看起来比式(1)复杂些,但它仅需做3次n/2位整数的乘法(AC,BD和(A-B)(D-C)),
// 6次加、减法和2次移位。由此可得:
//
//
// _
// | T(1) = 1
// | (4)
// |_T(n) = 3T(n/2) + cn
//
// 用解递归方程的套用公式法可解得T(n)=O(nlog3)=O(n1.59)。利用式(3),设计
// 算法如下:
//
// Multiply(X,Y,n) △ X和Y为2个小于2n的整数,返回结果为X和Y的乘积XY
// 1. S ← sign(X) * sign(Y) △ S为X和Y的符号乘积}
// 2. X ← abs(X)
// 3. Y ← abs(Y) △ X和Y分别取绝对值}
// 4. if n = 1
// 5. then if (X = 1) and (Y = 1)
// 6. then return S
// 7. else return(0)
// 8. else A ← X的左边n/2位
// 9. B ← X的右边n/2位
// 10. C ← Y的左边n/2位
// 11. D ← Y的右边n/2位
// 12. m1 ← Multiply(A, C, n / 2)
// 13. m2 ← Multiply(A - B, D - C, n / 2)
// 14. m3 ← Multiply(B, D, n / 2)
// 15. S ← S * (m1 * 2n + (m1 + m2 + m3) * 2n/2 + m3)
// 16. return S
//
/* calculate the multiply of x and y,
n is their Bit count(32,16,8,4,2,1).
*/
__int64 Multiply(__int32 x, __int32 y, unsigned int n)
{
__int64 s; // s is the sign of x*y
__int64 m1, // m1 = ac
m2, // m2 = (a-b)*(d-c)
m3; // m3 = bd
__int32 a, // x的左边n/2位
b, // x的右边n/2位
c, // y的左边n/2位
d; // y的右边n/2位
unsigned long temp1,temp2;
// initialize s
if ( (x > 0 && y < 0) || (x < 0 && y > 0))
{
s = -1;
// abs x and y
x = abs(x);
y = abs(y);
}
else
if ( x == 0 || y == 0 )
{
s = 0;
return 0;
}
else
s = 1;
if (n == 1) // 一位数
{
if (x == 1 && y ==1)
return (s);
else
return 0;
}
else
{
temp1 = (1 << (n / 2)) - 1;
if (n == 32)
temp2 = 0xFFFFFFFF;
else
temp2 = (1 << n) - 1;
a = (x & (temp2 - temp1)) >> (n / 2); // x的左边n/2位
b = x & temp1; // x的右边n/2位
c = (y & (temp2 - temp1)) >> (n / 2); // y的左边n/2位
d = y & temp1; // y的右边n/2位
n /= 2;
m1 = Multiply (a, c, (n)); // && 0xFFFFFFFF;
m2 = Multiply ((a-b), (d-c), (n)); // && 0xFFFFFFFF;
m3 = Multiply (b, d, (n)); // && 0xFFFFFFFF;
s = s * (m1 * (temp2 + 1) + (m1 + m2 + m3) * (temp1 + 1) + m3);
return (s);
}
}
以上算法在调试中发现:计算4字节的两数相乘时有错,不晓得是否范围越界。计算2字节或者以下都能通过的。很怪。希望能得到根本性的解答。谢过……