大数乘法 分治法

  1. #include<stdio.h>
  2. #include<memory.h>
  3. #include<math.h>
  4. #include<assert.h>
  5. #include<string.h>
  6. #include<malloc.h>
  7. #include<time.h>
  8. int max(int x,int y)
  9. {
  10.     return x>y?x:y;
  11. }
  12. typedef struct
  13. {
  14.     int *NumHead;
  15.     int size;
  16. }BigNumber;
  17. const size_t BigSize=sizeof(BigNumber);
  18. /*********************************************************************************/
  19. /*******************                                  思想                     **********************/
  20. /*               int n=31*log2    即表示一个int型整数表示成十进制需要n位,n计算得9                                  */
  21. /*              因此,可设进制为10^9,但因为base^2<=10^9,所以BigBase=10^4
  22.                  输出时转换成十进制在每个元素后面加相应位数的0即可                              */
  23. /********************************************************************************/
  24. const int BigBase = 10000;
  25. const int PerBitLen = 4;
  26. /*  (1+x+x^2+x^3+…+x^(n-2)+x^(n-1))^2多项式乘法,系统最大项为x^(n-1)项,最大系数为n,而如果原来每一项前面都是BigBase,那么最大系数就变成
  27. BigBase*BigBase*n了,最大系数可以用2^64存储,若要保证n足够大,就要缩小BigBase
  28. */
  29. BigNumber *add(BigNumber *a,BigNumber *b,int offset)//可通过偏移来计算各种加法,O(N)
  30. {
  31.     int nsize=a->size;
  32.     char mark=-1;
  33.     BigNumber *result=(BigNumber *)malloc(BigSize);
  34.     if(offset==0)
  35.     {
  36.         if(a->size>b->size)
  37.         {
  38.             nsize=a->size;
  39.             {
  40.                 BigNumber *newb=(BigNumber *)malloc(BigSize);
  41.                 newb->NumHead=(int *)malloc(4*nsize);
  42.                 newb->size=nsize;
  43.                 memset(newb->NumHead,0,4*(nsize-b->size));
  44.                 memcpy(newb->NumHead+nsize-b->size,b->NumHead,4*b->size);
  45.                 b=newb;
  46.             }
  47.             mark=1;
  48.         }
  49.         else if(a->size<b->size)
  50.         {
  51.             nsize=b->size;
  52.             {
  53.                 BigNumber *newa=(BigNumber *)malloc(BigSize);
  54.                 newa->NumHead=(int *)malloc(4*nsize);
  55.                 newa->size=nsize;
  56.                 memset(newa->NumHead,0,4*(nsize-b->size));
  57.                 memcpy(newa->NumHead+nsize-a->size,a->NumHead,a->size*4);
  58.                 a=newa;
  59.             }
  60.             mark=0;
  61.         }
  62.     }
  63.     else
  64.     {
  65.         if(a->size+offset>b->size)
  66.         {
  67.             nsize=a->size+offset;
  68.             {
  69.                 BigNumber *newa=(BigNumber *)malloc(BigSize);
  70.                 BigNumber *newb=(BigNumber *)malloc(BigSize);
  71.                 newb->NumHead=(int *)malloc(4*nsize);
  72.                 newb->size=nsize;
  73.                 memset(newb->NumHead,0,4*(nsize-b->size));
  74.                 memcpy(newb->NumHead+nsize-b->size,b->NumHead,4*b->size);
  75.                 b=newb;
  76.                 newa->NumHead=(int *)malloc(4*nsize);
  77.                 newa->size=nsize;
  78.                 memset(newa->NumHead+a->size,0,4*offset);
  79.                 memcpy(newa->NumHead,a->NumHead,a->size*4);
  80.                 a=newa;
  81.             }
  82.             mark=2;
  83.         }
  84.         else if(a->size+offset<=b->size)
  85.         {
  86.             nsize=b->size;
  87.             {
  88.                 BigNumber *newa=(BigNumber *)malloc(BigSize);
  89.                 newa->NumHead=(int *)malloc(4*nsize);
  90.                 newa->size=nsize;
  91.                 memset(newa->NumHead,0,4*nsize);
  92.                 memcpy(newa->NumHead+nsize-a->size-offset,a->NumHead,a->size*4);
  93.                 a=newa;
  94.             }
  95.             mark=0;
  96.         }
  97.     }
  98.     
  99.     result->NumHead=(int *)malloc(4*nsize);
  100.     result->size=nsize;
  101.     while(–nsize>=0)
  102.         result->NumHead[nsize]=a->NumHead[nsize]+b->NumHead[nsize];
  103.     if(mark==0)
  104.     {
  105.         free(a->NumHead);
  106.         free(a);
  107.     }
  108.     else if(mark==1)
  109.     {
  110.         free(b->NumHead);
  111.         free(b);
  112.     }
  113.     else if(mark==2)
  114.     {
  115.         free(a->NumHead);
  116.         free(b->NumHead);
  117.         free(a);
  118.         free(b);
  119.     }
  120.     
  121.     return result;
  122. }
  123. BigNumber *Merge(BigNumber * front,BigNumber * last,BigNumber * middle,int halfn)//整合函数 O(N)
  124. {
  125.     int i;
  126.     int carry=0,borrow=0;
  127.     BigNumber *mid=add(add(front,middle,0),last,0);//2次内存申请与释放
  128.     BigNumber *nonperfect=add(add(front,mid,halfn),last,halfn);//2
  129.     BigNumber *result=(BigNumber *)malloc(BigSize);
  130.     result->size=nonperfect->size+1;
  131.     result->NumHead=(int *)malloc(4*nonperfect->size+4);//1
  132.     result->NumHead[0]=0;
  133.     memcpy(result->NumHead+1,nonperfect->NumHead,4*nonperfect->size);
  134.     
  135.     for(i=nonperfect->size;i>=0;–i)
  136.     {
  137.         int temp;
  138.         result->NumHead[i]+=carry;
  139.         result->NumHead[i]-=borrow;
  140.         if((temp=result->NumHead[i])>=0)
  141.         {
  142.             carry=temp/BigBase;//进位
  143.             result->NumHead[i]=temp%BigBase;//余位
  144.             borrow=0;
  145.         }
  146.         else
  147.         {
  148.             carry=0;
  149.             if((-result->NumHead[i])%BigBase==0)
  150.             {
  151.                 borrow=(-result->NumHead[i])/BigBase;
  152.                 result->NumHead[i]=0;
  153.             }
  154.             else if(i!=0)//最高位无处借位
  155.             {
  156.                 borrow=(-result->NumHead[i])/BigBase+1;
  157.                 result->NumHead[i]+=borrow*BigBase;
  158.             }
  159.         }
  160.     }
  161.         
  162.     free(front->NumHead);
  163.     free(middle->NumHead);
  164.     free(last->NumHead);
  165.     free(mid->NumHead);
  166.     free(nonperfect->NumHead);
  167.     free(front);
  168.     free(middle);
  169.     free(last);
  170.     free(mid);
  171.     free(nonperfect);
  172.     if(result->NumHead[0]==0)
  173.     {
  174.         memcpy(result->NumHead,result->NumHead+1,(result->size-1)*4);
  175.         result->size–;
  176.     }
  177.     return result;
  178. }
  179. BigNumber * sub(BigNumber *a,BigNumber *b)//差函数,不考虑借位与进位,O(N),2次内存释放与申请
  180. {
  181.     int nsize=a->size;
  182.     char mark=0;
  183.     BigNumber *diff=(BigNumber *)malloc(BigSize);
  184.     if(a->size>b->size)
  185.     {
  186.         BigNumber *c=(BigNumber *)malloc(BigSize);
  187.         c->NumHead=(int *)malloc(4*a->size);
  188.         c->size=a->size;
  189.         memset(c->NumHead,0,4*(a->size-b->size));
  190.         memcpy(c->NumHead+a->size-b->size,b->NumHead,4*b->size);
  191.         b=c;
  192.         nsize=a->size;
  193.         mark=1;
  194.     }
  195.     else if(b->size>a->size)
  196.     {
  197.         BigNumber *c=(BigNumber *)malloc(BigSize);
  198.         c->NumHead=(int *)malloc(4*b->size);
  199.         c->size=b->size;
  200.         memset(c->NumHead,0,4*(b->size-a->size));
  201.         memcpy(c->NumHead+b->size-a->size,a->NumHead,4*a->size);
  202.         a=c;
  203.         nsize=b->size;
  204.         mark=-1;
  205.     }
  206.     diff->NumHead=(int *)malloc(nsize*4);
  207.     diff->size=nsize;
  208.     while(–nsize>=0)
  209.         diff->NumHead[nsize]=a->NumHead[nsize]-b->NumHead[nsize];
  210.     if(mark==-1)
  211.     {
  212.         free(a->NumHead);
  213.         free(a);
  214.     }
  215.     else if(mark==1)
  216.     {
  217.         free(b->NumHead);
  218.         free(b);
  219.     }
  220.     
  221.     return diff;
  222. }
  223. BigNumber *Mutiply(BigNumber *a,BigNumber *b)//
  224. {
  225.     int nsize=max(a->size,b->size);
  226.         
  227.     if(a->size!=nsize)
  228.     {
  229.         BigNumber *c=(BigNumber *)malloc(BigSize);
  230.         c->NumHead=(int *)malloc(4*nsize);
  231.         c->size=nsize;
  232.         memset(c->NumHead,0,4*(nsize-a->size));
  233.         memcpy(c->NumHead+nsize-a->size,a->NumHead,4*a->size);
  234.         free(a->NumHead);
  235.         free(a);
  236.         a=c;
  237.     }
  238.     if(b->size!=nsize)
  239.     {
  240.         BigNumber *c=(BigNumber *)malloc(BigSize);
  241.         c->NumHead=(int *)malloc(4*nsize);
  242.         c->size=nsize;
  243.         memset(c->NumHead,0,4*nsize);
  244.         memcpy(c->NumHead+nsize-b->size,b->NumHead,4*b->size);
  245.         free(b->NumHead);
  246.         free(b);
  247.         b=c;
  248.     }
  249.     //对齐并变双
  250.     
  251.     if(nsize==1)
  252.     {
  253.         BigNumber *result=(BigNumber *)malloc(BigSize);
  254.         long long temp=(long long)(a->NumHead[0])*(long long)(b->NumHead[0]);
  255.         if(temp/BigBase==0)
  256.         {
  257.             result->NumHead=(int *)malloc(4);
  258.             result->NumHead[0]=(int)temp;
  259.             result->size=1;
  260.         }
  261.         else
  262.         {
  263.             result->NumHead=(int *)malloc(8);
  264.             result->NumHead[1]=(int)(temp%BigBase);
  265.             result->NumHead[0]=(int)(temp/BigBase);
  266.             result->size=2;
  267.         }
  268.         
  269.         free(a->NumHead);
  270.         free(b->NumHead);
  271.         free(a);
  272.         free(b);
  273.         
  274.         return result;
  275.     }
  276.     else
  277.     {
  278.         int left=nsize/2;
  279.         int right=nsize-left;
  280.         
  281.         BigNumber *a1=(BigNumber *)malloc(BigSize);
  282.         BigNumber *a2=(BigNumber *)malloc(BigSize);
  283.         BigNumber *b1=(BigNumber *)malloc(BigSize);
  284.         BigNumber *b2=(BigNumber *)malloc(BigSize);
  285.         
  286.         a1->size=b1->size=left;
  287.         a2->size=b2->size=right;
  288.         a1->NumHead=(int *)malloc(4*left);
  289.         b1->NumHead=(int *)malloc(4*left);
  290.         a2->NumHead=(int *)malloc(4*right);
  291.         b2->NumHead=(int *)malloc(4*right);
  292.         memcpy(a1->NumHead,a->NumHead,4*left);
  293.         memcpy(b1->NumHead,b->NumHead,4*left);
  294.         memcpy(a2->NumHead,a->NumHead+left,4*right);
  295.         memcpy(b2->NumHead,b->NumHead+left,4*right);
  296.         free(a->NumHead);
  297.         free(b->NumHead);
  298.         free(a);
  299.         free(b);
  300.         nsize=nsize%2!=0?nsize+1:nsize;
  301.         return Merge(Mutiply(a1,b1),Mutiply(a2,b2),Mutiply(sub(a2,a1),sub(b1,b2)),nsize/2);
  302.     }
  303. }
  304. /////////////////////////////////初始化/////////////////////////////////////
  305. BigNumber *Int_BigInit(int tar)
  306. {
  307.     int bitlen=(int)log10((long double)tar)/PerBitLen+1;
  308.     BigNumber *Big=(BigNumber *)malloc(BigSize);
  309.     Big->NumHead=(int *)malloc(4*bitlen);
  310.     assert(Big!=NULL);
  311.     Big->size=bitlen;
  312.     //memset(Big->NumHead,0,4*(bitlen));
  313.     while(–bitlen>=0)
  314.     {
  315.         Big->NumHead[bitlen]=tar%BigBase;
  316.         tar/=BigBase;
  317.     }
  318.     return Big;
  319. }
  320. int BaseChange(char *str,int low,int up)
  321. {
  322.     int i=up;
  323.     int sum=0;
  324.     
  325.     for(;i>=low;–i)
  326.     {
  327.         if(str[i]==‘0’)continue;
  328.         if(str[i]<‘0’||str[i]>‘9’)return -1;
  329.         sum+=(str[i]-‘0’)*((int)pow((double)10,(double)up-i));
  330.     }
  331.     return sum;
  332. }
  333. BigNumber *Str_BigInit(char * str)
  334. {
  335.     int strlenth,bitlen;
  336.     int i=0,k=0;
  337.     BigNumber *Big;
  338.     assert(str!=NULL);
  339.     while(*str++==‘0’);
  340.     strlenth=strlen(–str);
  341.     bitlen=strlenth/PerBitLen;
  342.     /*strlenth–;
  343.     bitlen–;*/
  344.     if(strlenth%PerBitLen!=0)
  345.         ++bitlen;
  346.     Big=(BigNumber *)malloc(BigSize);
  347.     Big->NumHead=(int *)malloc(4*(bitlen));
  348.     //memset(Big->NumHead,0,4*(len+1));
  349.     Big->size=bitlen;
  350.     assert(Big->NumHead!=NULL);
  351.     for(;bitlen>0;–bitlen,strlenth-=PerBitLen)
  352.     {
  353.         int max= strlenth-1;
  354.         int min=strlenth-PerBitLen;
  355.         min=min<0?0:min;
  356.         Big->NumHead[bitlen-1]=BaseChange(str,min,max);
  357.     }
  358.     return Big;
  359. }
  360. /////////////////////////////////////////////////////////////////////////////
  361. void BigPrint(BigNumber * result,FILE *fp)
  362. {
  363.     int i=0;
  364.     assert(result!=NULL&&result->NumHead!=NULL);
  365.     while(result->NumHead[i++]==0);
  366.     fprintf(fp,“%d”,result->NumHead[i++]);
  367.     for(;i<result->size;++i)
  368.     {
  369.         fprintf(fp,“%04d”,result->NumHead[i]);
  370.         //fprintf(fp,”%01d”,result->NumHead[i]);
  371.     }
  372.     fprintf(fp,“/n”);
  373. }
  374. BigNumber * Factorial(int n)//测试阶乘
  375. {
  376.     if(n==0||n==1)
  377.         return Int_BigInit(n);
  378.     else return Mutiply(Int_BigInit(n),Factorial(n-1));
  379. }
  380. int main()
  381. {
  382.     //printf(“%d”,sizeof(long long));
  383.     int i=0;
  384.     clock_t start, finish; 
  385.     //fscanf(stdin,”%d”,&i);
  386.     start=clock();
  387.     BigPrint(Mutiply(Str_BigInit(“99912344444445384759347523452”),Str_BigInit(“11345623453452345235”)),stdout);
  388.     finish=clock();
  389.     printf(“用时 %lf 秒/n”,(double)(finish – start) / CLOCKS_PER_SEC);
  390.     //BigPrint(BigMutiply(Str_BigInit(“479001600”),Int_BigInit(13)),stdout);
  391.     return 0;
  392. }
  393. //程序频繁的申请与释放内存是个缺点,乘法复杂度为O(N 1.59),
    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/fuchuangbob/article/details/3220156
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞