分治算法介绍
给定两个n位的二进制整数x和y(当然次算法不限定二进制数),作为x乘y的第一步,我们将x和y一分为二,每个数的左半部分和右半部分都是n/2位的二进制整数:
例如,如果X=10110110B(B表示该数是二进制数),那么XL=1011B, XR=0110B, 同时X=1011B*2^4+0110B. x和y的乘积从而可以写为以下形式:
看上去我们要进行4次实数乘法(乘2的幂相当于左移运算不考虑),实际上,类似上面引言的介绍,只需要进行三次乘法:XLYL,XRYR,(XL + XR)(YL + YR), 因为XLYR + XRYL = (XL + XR)(YL + YR) - XLYL - XRYR
运行时间改进为O(n^1.59)。
#include<iostream> #include<cmath> using namespace std; #define SIGN(A) ((A>0)?1:-1)//定义一个符号函数表示正负 int multiply(int x, int y,int n) { int sign = SIGN(x)*SIGN(y); int XR, XL, YR, YL; int P1, P2, P3; if (x == 0 || y == 0) return 0; if (n == 1) return x*y; else { //计算X和y的各个部分 XL = x / pow(10, n / 2); XR = x - XL*(pow(10, n / 2)); YL = y / pow(10, n / 2); YR = y - YL*(pow(10, n / 2)); //分治计算 P1 = multiply(XL, YL, n-n/2); P2 = multiply(XR, YR, n / 2); P3 = multiply(XL + XR, YL + YR, n-n/2); return sign*(P1*pow(10, 2*floor(n/2)) + (P3 - P1 - P2)*pow(10,n/2) + P2); } } int main() { printf("请输入两个等长的数字x和y...\n"); int x, y, n; printf("请输入x:\n"); cin >> x; printf("请输入y:\n"); cin >> y; printf("请输入x和y的位数:\n"); cin >> n; printf("---------------------------------------------\n"); printf("x * y = "); cout<<multiply(x, y, n)<<endl; printf("非分治算法求得 x * y = "); cout << x*y<<endl; system("pause"); return 0; }
转载