- 刚发现个问题,,初学时竟然是使用的long型进行计算的,导致这篇文章虽展现了分治的想法,但并没有实际解决大整数乘法的计算问题。
- 仅供参考,日后再改
一、大整数乘法
- 一般计算方法
- 有n位大整数X和Y,计算XY:将Y的每一位与X相乘再按位相加;
- 时间复杂度:我们需要进行一次n位的乘法,即 T ( n ) = o ( n 2 ) T(n)=o(n^2) T(n)=o(n2)
- 分治法(理想状态下)
-
理想状态:假设有n位大整数X和Y(X和Y位数n相同且为偶数),计算XY。
-
分治:我们将X、Y分别拆分为a与b、c与d, X = a ∗ 1 0 ⌊ n / 2 ⌋ + b X=a*10^{\left \lfloor n/2 \right \rfloor}+b X=a∗10⌊n/2⌋+b, Y = c ∗ 1 0 ⌊ n / 2 ⌋ + d Y=c*10^{\left \lfloor n/2 \right \rfloor}+d Y=c∗10⌊n/2⌋+d
再计算:
X Y = a c ∗ 1 0 2 ⌊ n / 2 ⌋ + ( a d + b c ) ∗ 1 0 ⌊ n / 2 ⌋ + b d XY=ac*10^{2{\left \lfloor n/2 \right \rfloor}}+(ad+bc)*10^{\left \lfloor n/2 \right \rfloor}+bd XY=ac∗102⌊n/2⌋+(ad+bc)∗10⌊n/2⌋+bd -
时间复杂度:一共需要进行4次n/2的乘法(ac,ad,bc、bd各一次)和3次加法,
因而 T ( n ) = 4 T ( n / 2 ) + θ ( n ) = o ( n 2 ) T(n)=4T(n/2)+\theta(n)=o(n^2) T(n)=4T(n/2)+θ(n)=o(n2) -
改善:设 E = a c , F = b d , G = ( a − b ) ∗ ( d − c ) = a d − b d − a c + b c E=ac,F=bd,G=(a-b)*(d-c)=ad-bd-ac+bc E=ac,F=bd,G=(a−b)∗(d−c)=ad−bd−ac+bc,则
X Y = E ∗ 1 0 2 ⌊ n / 2 ⌋ + ( G + E + F ) ∗ 1 0 ⌊ n / 2 ⌋ + F XY=E*10^{2{\left \lfloor n/2 \right \rfloor}}+(G+E+F)*10^{\left \lfloor n/2 \right \rfloor}+F XY=E∗102⌊n/2⌋+(G+E+F)∗10⌊n/2⌋+F -
改善后的时间复杂度:一共需要进行3次n/2的乘法(E,F,G各一次)和4次加法,
因而 T ( n ) = 3 T ( n / 2 ) + θ ( n ) = o ( n 1.59 ) T(n)=3T(n/2)+\theta(n)=o(n^{1.59}) T(n)=3T(n/2)+θ(n)=o(n1.59)
-
- 分治法(非理想状态下)
-
非理想状态:假设有 n x n_x nx位大整数X和 n y n_y ny位大整数Y(X和Y位数n大小随机),计算XY。
-
分治:我们将X、Y分别拆分为a与b、c与d, X = a ∗ 1 0 ⌊ n x / 2 ⌋ + b X=a*10^{\left \lfloor n_x/2 \right \rfloor}+b X=a∗10⌊nx/2⌋+b, Y = c ∗ 1 0 ⌊ n y / 2 ⌋ + d Y=c*10^{\left \lfloor n_y/2 \right \rfloor}+d Y=c∗10⌊ny/2⌋+d
再计算:
X Y = a c ∗ 1 0 ⌊ n x / 2 ⌋ + ⌊ n y / 2 ⌋ + ( a d ∗ 1 0 ⌊ n x / 2 ⌋ + b c ∗ 1 0 ⌊ n y / 2 ⌋ ) + b d XY=ac*10^{{\left \lfloor n_x/2 \right \rfloor}+{\left \lfloor n_y/2 \right \rfloor}}+(ad*10^{\left \lfloor n_x/2 \right \rfloor}+bc*10^{\left \lfloor n_y/2 \right \rfloor})+bd XY=ac∗10⌊nx/2⌋+⌊ny/2⌋+(ad∗10⌊nx/2⌋+bc∗10⌊ny/2⌋)+bd -
时间复杂度:一共需要进行4次 n x / 2 n_x/2 nx/2乘 n y / 2 n_y/2 ny/2的乘法和3次加法,
因而 T ( n ) = . . . T(n)=... T(n)=... -
改善:设 E = a c , F = b d , G = ( a ∗ 1 0 n x / 2 − b ) ∗ ( d − c ∗ 1 0 n y / 2 ) E=ac,F=bd,G=(a*10^{n_x/2}-b)*(d-c*10^{n_y/2}) E=ac,F=bd,G=(a∗10nx/2−b)∗(d−c∗10ny/2),则
X Y = E ∗ 1 0 ⌊ n x / 2 ⌋ + ⌊ n y / 2 ⌋ + ( G + E ∗ 1 0 ⌊ n x / 2 ⌋ + ⌊ n y / 2 ⌋ + F ) + F XY=E*10^{{\left \lfloor n_x/2 \right \rfloor}+{\left \lfloor n_y/2 \right \rfloor}}+(G+E*10^{{\left \lfloor n_x/2 \right \rfloor}+{\left \lfloor n_y/2 \right \rfloor}}+F)+F XY=E∗10⌊nx/2⌋+⌊ny/2⌋+(G+E∗10⌊nx/2⌋+⌊ny/2⌋+F)+F -
改善后的时间复杂度:一共需要进行3次 n x / 2 n_x/2 nx/2乘 n y / 2 n_y/2 ny/2的乘法和4次加法,
因而 T ( n ) = . . . T(n)=... T(n)=...
-
二、递归算法实现
1. 设计递归方程
- 理想状态下;
X Y = E ∗ 1 0 2 ⌊ n / 2 ⌋ + ( G + E + F ) ∗ 1 0 ⌊ n / 2 ⌋ + F XY=E*10^{2{\left \lfloor n/2 \right \rfloor}}+(G+E+F)*10^{\left \lfloor n/2 \right \rfloor}+F XY=E∗102⌊n/2⌋+(G+E+F)∗10⌊n/2⌋+F - 非理想状态下;
X Y = E ∗ 1 0 ⌊ n x / 2 ⌋ + ⌊ n y / 2 ⌋ + ( G + E ∗ 1 0 ⌊ n x / 2 ⌋ + ⌊ n y / 2 ⌋ + F ) + F XY=E*10^{{\left \lfloor n_x/2 \right \rfloor}+{\left \lfloor n_y/2 \right \rfloor}}+(G+E*10^{{\left \lfloor n_x/2 \right \rfloor}+{\left \lfloor n_y/2 \right \rfloor}}+F)+F XY=E∗10⌊nx/2⌋+⌊ny/2⌋+(G+E∗10⌊nx/2⌋+⌊ny/2⌋+F)+F - 当拆分后的子整数的位数为1时,结束递归。
2. 编写程序代码
- 理想状态下;
// 大整数乘法--理想状态
#include <iostream>
#include <cmath>
using namespace std;
int SIGN(long A);
long bigIntMultiply_Ideal(long X, long Y, int n);
int main()
{
long X = 0;
long Y = 0;
int n = 0;
cout << "大整数乘法:请输入两个大整数:\n";
cout << "X=";
cin >> X;
cout << "Y=";
cin >> Y;
cout << "请输入两个大整数的长度:n=";
cin >> n;
cout << "\nX*Y=" << bigIntMultiply_Ideal(X, Y, n) << endl;
return 0;
}
int SIGN(long A)
{
return A > 0 ? 1 : -1;
}
long bigIntMultiply_Ideal(long X, long Y, int n)
{
// a-b和d-c可能为负值
int sign = SIGN(X) * SIGN(Y);
X = abs(X);
Y = abs(Y);
if (X == 0 || Y == 0)
return 0;
else if (n == 1)
return sign * X * Y;
else
{
long a = (long)(X / pow(10, n / 2));
long b = (X % (long)pow(10, n / 2));
long c = (long)(Y / pow(10, n / 2));
long d = (Y % (long)pow(10, n / 2));
long E = bigIntMultiply_Ideal(a, c, n / 2); // E=a*c
long F = bigIntMultiply_Ideal(b, d, n / 2); // F=b*d
long G = bigIntMultiply_Ideal((a - b), (d - c), n / 2) + E + F; // G=(a-b)*(d-c)+bd+ac
return (long)(sign * (E * pow(10, n) + G * pow(10, n / 2) + F));
}
}
- 非理想状态下;
// 大整数乘法--非理想状态
#include <iostream>
#include <cmath>
using namespace std;
int SIGN(long A);
long bigIntMultiply_Nonideal(long X, long Y, int n_x, int n_y);
int main()
{
long X = 0;
long Y = 0;
int n_x = 0;
int n_y = 0;
cout << "大整数乘法:请输入两个大整数:\n";
cout << "X=";
cin >> X;
cout << "Y=";
cin >> Y;
cout << "请输入大整数X的长度:n_x=";
cin >> n_x;
cout << "请输入大整数Y的长度:n_y=";
cin >> n_y;
cout << "\nX*Y=" << bigIntMultiply_Nonideal(X, Y, n_x, n_y) << endl;
return 0;
}
int SIGN(long A)
{
return A > 0 ? 1 : -1;
}
long bigIntMultiply_Nonideal(long X, long Y, int n_x, int n_y)
{
if (X == 0 || Y == 0)
return 0;
else if ((n_x == 1 && n_y == 1) || n_x == 1 || n_y == 1)
return X * Y;
else
{
int n_x0 = n_x / 2;
int n_x1 = n_x - n_x0;
int n_y0 = n_y / 2;
int n_y1 = n_y - n_y0;
long a = (long)(X / pow(10, n_x0));
long b = (long)(X % (long)pow(10, n_x0));
long c = (long)(Y / pow(10, n_y0));
long d = (long)(Y % (long)pow(10, n_y0));
long E = bigIntMultiply_Nonideal(a, c, n_x1, n_y1);
long F = bigIntMultiply_Nonideal(b, d, n_x0, n_y0);
long G = bigIntMultiply_Nonideal((long)(a * pow(10, n_x0) - b), (long)(d - c * pow(10, n_y0)), n_x1, n_y1);
return (long)(E * pow(10, (n_x0 + n_y0)) + (G + E * pow(10, (n_x0 + n_y0)) + F) + F);
}
}
3. 运行结果展示
- 理想状态下;
- 非理想状态下;
(注:运行计算的整数并不足够大,这里仅仅是举个栗子!)
三、友情链接~
- 其它一些常见算法请参阅此链接~
最后,非常欢迎大家来讨论指正哦!