正文

分治法求大数乘2007-03-20 12:45:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lingdlz/24130.html

分享到:

/************************分治法求大数乘,这种方法是比较好的,听说还有快的算法,我一定可以找到的  思路 : 123 * 456 分治如下  第一次拆分:  12   45 (拆分方法 设 char *a = "123" ,*b = "456" 对 a: t = strlen(a)  t/2 得 12(0,1位置) 余者 3(2位置)为       3    6 ( 另一部分,对 b 亦同,即拆分为 45 6,如左)   递归求:  12 * 45     ( 求得 12 * 45 的解果左移两位补0右边,因为其实是 120 * 450 )    12 * 6      ( 同上左移一位其实是120 * 6 )     3 * 45     ( 3 * 450 )     3 * 6      ( 3 * 6 解果不移动 )    第二次拆分(12 * 45 ) ( 如下 )    1    4      ( 交叉相乘并将结果相加 1 * 4 左移两位 400 ,1 * 5 左移一位 50 ,2 * 4 左移一位 80 ,2 * 5 不移为 10)        2    5      ( 相加得400 + 50 + 80 + 10 = 540 )  另外几个不需要拆分 得 72 , 135 , 18 所以: 54000 + 720 + 1350 + 18 = 56088  难点是对分治的理解,以及结果的调整,对结果的合并. 编译环境: VC ++ 6.0  Author : 江南孤峰  Time : 2006--10--26  *************************/ #include <stdio.h>#include <malloc.h>#include <stdlib.h>#include <string.h> char *result = '\0';int  pr = 1; void getFill(char *a,char *b,int ia,int ja,int ib,int jb,int tbool,int move){    int  r,m,n,s,j,t;    char *stack;        m = a[ia] - 48;    if( tbool ){// 直接从结果数组的标志位填入,这里用了堆栈思想        r = (jb - ib > ja - ia) ? (jb - ib) : (ja - ia);        stack = (char *)malloc(r + 4);          for(r = j = 0,s = jb; s >= ib; r ++,s --){            n = b[s] - 48;            stack[r] = (m * n + j) % 10;            j = (m * n + j) / 10;        }        if( j ){            stack[r] = j;            r ++;        }        for(r --; r >= 0; r --,pr ++)            result[pr] = stack[r];        free(stack);        for(move = move + pr; pr < move; pr ++)            result[pr] = '\0';    }    else{ //与结果的某几位相加,这里不改变标志位 pr 的值        r = pr - move - 1;        for(s = jb,j = 0; s >= ib; r --,s --){            n = b[s] - 48;            t = m * n + j + result[r];            result[r] = t % 10;            j = t / 10;        }        for( ; j ; r -- ){            t = j + result[r];            result[r] = t % 10;            j = t / 10;        }    } } int  get(char *a,char *b,int ia,int ja,int ib,int jb,int t,int move){    int m,n,s,j;        if(ia == ja){        getFill(a,b,ia,ja,ib,jb,t,move);        return 1;    }    else if(ib == jb){        getFill(b,a,ib,jb,ia,ja,t,move);        return 1;    }    else{        m = (ja + ia) / 2;        n = (jb + ib) / 2;        s = ja - m;        j = jb - n;        get(a,b,ia,m,ib,n,t,s + j + move);          get(a,b,ia,m,n + 1,jb,0,s + move);        get(a,b,m + 1,ja,ib,n,0,j + move);        get(a,b,m + 1,ja,n + 1,jb,0,0 + move);    }    return 0;} int  main(){    char *a,*b;    int  n,flag;        a = (char *)malloc(1000);    b = (char *)malloc(1000);    printf("The program will computer a*b\n");    printf("Enter a b:");    scanf("%s %s",a,b);    result = (char *)malloc(strlen(a) + strlen(b) + 2);    flag = pr = 1;    result[0] = '\0';    if(a[0] == '-' && b[0] == '-')        get(a,b,1,strlen(a)-1,1,strlen(b)-1,1,0);    if(a[0] == '-' && b[0] != '-'){        flag = 0;        get(a,b,1,strlen(a)-1,0,strlen(b)-1,1,0);    }    if(a[0] != '-' && b[0] == '-'){        flag = 0;        get(a,b,0,strlen(a)-1,1,strlen(b)-1,1,0);    }    if(a[0] != '-' && b[0] != '-')        get(a,b,0,strlen(a)-1,0,strlen(b)-1,1,0);    if(!flag)        printf("-");    if( result[0] )        printf("%d",result[0]);    for(n = 1; n < pr ; n ++)        printf("%d",result[n]);    printf("\n");    free(a);    free(b);    free(result);    system("pause");    return 0;}    /**************对 get() 函数参数的解释:计算:123*435:int  get(char *a,char *b,int ia,int ja,int ib,int jb,int t,int move); a:        存储数 m的字符数组(123)b:        存储数 n的字符数组(435)(ia,ja): 决定当前分治的数,最开始为(0,strlen(a)-1),即123(ib,jb): 决定当前分治的数,最开始为(0,strlen(b)-1),即435t:        标志值,1,0代表不同的填充方式,举例:          123 * 435 ,拆分顺序如下:          12 * 43  get(a,b,0,1,0,1,1,2);  (t 为1,表示本次结果直接填入)          12 * 5   get(a,b,0,1,,2,2,0,1);          3 * 43   get(a,b,2,2,0,1,0,1);          3 * 5    get(a,b,2,2,2,2,0,0);          .... move:     结果的移动值如: 12*43 的最后结果为516,实际是120*430          所以左移2位即将 51600填入 result  求 123*435 的简要顺序:  12*43 = 516 左移两位得 51600 直接填入: result = "51600"  12*5  = 60  左移一位得 600   间接填入: result = "52200"  3*43  = 129 左移一位得 1290  间接填入: result = "53490"  3*5   = 15  不需要移动,将15 间接填入: result = "53505"  所以123*435 = 53505****************/

阅读(4915) | 评论(3)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册