zoukankan      html  css  js  c++  java
  • 大数乘法

    分治算法首先讲了一个经典的乘法运算

    具体的代码如下:  该算法的核心是计算xy=(10^n/2xl+xr)(10^n/2yl+yr)=10^nxlyl+10^n/2(xlyr+xryl)+xryr

     1 /************************************************************************/
     2 //函数功能:分治法求两个位数为N的整数的乘积
     3 //输入参数:X,Y分别为两个位数为N的整数
     4 //算法思想:分治算法,xy=(10n/2xl+xr)(10n/2yl+yr)=10nxlyl+10n/2(xlyr+xryl)+xryr
     5 //时间复杂度为:T(n)=O(nlog3)=O(n1.59)
     6 /************************************************************************/
     7 #include <iostream>
     8 #include <cmath>
     9 using namespace std;
    10 #define SIGN(A) ((A > 0) ? 1 : -1)
    11 
    12 int IntegerMultiply(int X, int Y, int N)
    13 {
    14     int sign = SIGN(X) * SIGN(Y);   //确定结果的符号 
    15     int x = abs(X);                 //取绝对值,去掉x,y符号 
    16     int y = abs(Y);
    17     if((0 == x) || (0 == y))
    18         return 0;
    19     if (1 == N)
    20         return x*y;
    21     else
    22     {
    23         int XL = x / (int)pow(10., (int)N/2); 
    24         int XR = x - XL * (int)pow(10., N/2);
    25         int YL = y / (int)pow(10., (int)N/2);
    26         int YR = y - YL * (int)pow(10., N/2);
    27         
    28         int XLYL = IntegerMultiply(XL, YL, N/2);
    29         int XRYR = IntegerMultiply(XR, YR, N/2);
    30         int XLYRXRYL = IntegerMultiply(XL - XR, YR - YL, N/2) + XLYL + XRYR;
    31         return sign * (XLYL * (int)pow(10., N) + XLYRXRYL * (int)pow(10., N/2) + XRYR);
    32     }
    33 }
    34 
    35 int main()
    36 {
    37     int x = 1234;
    38     int y = 4321;
    39     cout<<"x * y = "<<IntegerMultiply(x, y, 4)<<endl;
    40     cout<<"x * y = "<<x*y<<endl;
    41     return 0;
    42 }

    另外搜索到了一个很不错的大数程序,这里先mark一下:

      1 //设计一个支持大数运算的计算器,其中乘法使用分治法求解。该计算器支持加减乘除还有开方根运算。
      2 #include <iostream>
      3 #include <list>
      4 #include <string>
      5 #include <cstdio>
      6 #include <cctype>
      7 #include <cmath>
      8 using namespace std;
      9 list<char> Add(list<char> s, list<char> t);
     10 list<char> Sub(list<char> s, list<char> t);
     11 list<char> Mul(list<char> s, list<char> t);
     12 void Div(list<char> s, list<char> t);
     13 void  Root(list<char>);
     14 void print(list<char> ans);
     15 void printhelp()             //打印帮助信息
     16 {
     17     cout << "请选择要进行的大数运算" << endl;
     18     cout << "1:加法运算" << endl;
     19     cout << "2:减法运算" << endl;
     20     cout << "3:乘法运算" << endl;
     21     cout << "4:除法运算" << endl;
     22     cout << "5:开平方根运算" << endl;
     23     cout << "6:退出" << endl;
     24 }
     25 list<char> Add(list<char> num1,list<char> num2)  //加法运算
     26 {
     27     list<char> ans;
     28     list<char>::iterator iter1,iter2;
     29     iter1 = num1.begin();
     30     iter2 = num2.begin();
     31     int sign = 0;                                   //标记结果符号
     32     if((*iter1) == '-' && (*iter2) == '-')        //如果两个数都是负数
     33     {
     34         num1.pop_front();
     35         num2.pop_front();
     36         sign = 1;
     37         ans = Add(num1,num2);
     38         ans.push_front('-');
     39     }
     40     else if((*iter1) == '-' && (*iter2) != '-')      //如果一负一正
     41     {
     42         num1.pop_front();
     43         ans = Sub(num2,num1);
     44         
     45     }
     46     else if((*iter1) != '-' && (*iter2) == '-')      //如果一正一负
     47     {
     48         num2.pop_front();
     49         ans = Sub(num1,num2);
     50     }
     51     else                                          //如果都为正
     52     {
     53         int len1,len2,i,len,carry;
     54         len1 = num1.size();
     55         len2 = num2.size();
     56         if(len1 >= len2)                     //补齐两个数的位数
     57         {
     58             len = len1;
     59             for(i = 0; i < len1 - len2; i++)
     60                 num2.push_front('0');
     61         }
     62         else
     63         {
     64             len = len2;
     65             for(i = 0; i < len2 - len1; i++)
     66                 num1.push_front('0');
     67         }
     68         //print(num1);
     69         //print(num2);
     70         carry = 0;
     71         iter1 = num1.end();
     72         iter2 = num2.end();
     73         iter1--;
     74         iter2--;
     75         for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2)  //进行运算
     76         {
     77             i = (*iter1 - '0') + (*iter2 - '0') + carry;
     78             //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
     79             ans.push_front((i % 10) + '0');
     80             carry = i / 10;
     81         }
     82         i = (*iter1 - '0') + (*iter2 - '0') + carry;
     83         //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
     84         ans.push_front((i % 10) + '0');
     85         carry = i / 10;
     86         if(carry)
     87             ans.push_front(carry+'0');
     88     }
     89     return ans;                                                     //返回结果
     90 }
     91 list<char> Sub(list<char> num1,list<char> num2)                    //减法运算
     92 {
     93     list<char> ans;
     94     int sign = 0;
     95     list<char>::iterator iter1,iter2;
     96     int len1,len2,len;
     97     iter1 = num1.begin();
     98     iter2 = num2.begin();
     99     if((*iter1) == '-' && (*iter2) == '-')                  //如果两个数都为负数
    100     {
    101         num2.pop_front();
    102         num1.pop_front();
    103         ans = Sub(num2,num1);
    104         //ans.push_front('-');
    105     }
    106     else if( (*iter1) == '-' && (*iter2) != '-')              //如果一负一正
    107     {
    108         num1.pop_front();
    109         ans = Add(num1,num2);
    110         ans.push_front('-');
    111     }
    112     else if( (*iter1) != '-' && (*iter2) == '-')              //如果一正一负
    113     {
    114         num2.pop_front();
    115         ans = Add(num1,num2);
    116         
    117     }
    118     else                                                   //如果都为正
    119     {
    120         len1 = num1.size();
    121         len2 = num2.size();
    122         if(len1 >= len2)                                 //补齐位数
    123         {
    124             len = len1;
    125             for(int i = 0; i < len1 - len2; i++)
    126                 num2.push_front('0');
    127         }
    128         else
    129         {
    130             len = len2;
    131             for(int i = 0; i < len2 - len1; i++)
    132                 num1.push_front('0');
    133         }
    134         //print(num1);cout << endl;
    135         //print(num2);cout << endl;
    136         int carry = 0,i;
    137         iter1 = num1.end();
    138         iter2 = num2.end();
    139         iter1--;
    140         iter2--;
    141         for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2)    //进行运算
    142         {
    143             i = (*iter1 - '0' - carry) - (*iter2 - '0');
    144             carry = 0;
    145             if( i < 0)
    146             {
    147                 i += 10;
    148                 carry = 1;
    149             }
    150             //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
    151             ans.push_front((i % 10) + '0');
    152         }
    153         i = (*iter1 - '0' - carry) - (*iter2 - '0');
    154         if(i < 0)
    155         {
    156             i += 10;
    157             sign = 1;
    158         }
    159         //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl;
    160         if(i) ans.push_front(i + '0');
    161         if(sign)
    162             ans.push_front('-');
    163     }
    164     return ans;
    165 }
    166 list<char> Mul(list<char> num1,list<char> num2)  // 分治法求两大数的积
    167 {
    168     list<char> ans;
    169     int sign = 0;
    170     int len1,len2,len;
    171     list<char>::iterator iter1,iter2,iter;
    172     list<char> high,low;
    173     list<char> anshigh,anslow;
    174     int th,tl;
    175     int i,j,k;
    176     //print(num1);cout << endl;
    177     //print(num2);cout << endl;
    178     if(num1.size() == 1 && num2.size() == 1)     //如果两数都已是一位数,则进行运算
    179     {
    180         th = *(num1.begin()) - '0';
    181         tl = *(num2.begin()) - '0';
    182         th *= tl;
    183         ans.push_front( th % 10 + '0');
    184         ans.push_front( th / 10 + '0');
    185         return ans;
    186     }
    187     else if(num1.size() == 1 && num2.size() > 1)            //如果num1位数大于1,则对Num1分治求积
    188     {
    189          if(*(num2.begin()) == '-')
    190            {
    191                 sign = 1;
    192                 num2.pop_front();
    193            }
    194          len2 = num2.size();
    195          if(len2 == 1)
    196          {
    197             ans = Mul(num1,num2);
    198             if(sign)
    199                 ans.push_front('-');
    200          }
    201          else
    202          {
    203             for(iter= num2.begin(),i = 0; i < len2 / 2; i++,iter++)
    204             {
    205                 high.push_back(*iter);
    206             }
    207             for(;iter!=num2.end();iter++)
    208             {
    209                 low.push_back(*iter);
    210             }
    211             len = low.size();
    212             anshigh = Mul(num1,high);                 //num1分为两部分,high,low
    213             anslow = Mul(num1,low);
    214             for(i = 0; i < len; i++)
    215                 anshigh.push_back('0');
    216             ans = Add(anshigh,anslow);                 //合并结果
    217             if(sign)
    218                 ans.push_front('-');
    219          }
    220          return ans;
    221     }
    222     else if(num2.size() == 1 && num1.size() > 1)              //如果num2位数大于1,则对Num2分治求积
    223     {
    224          if(*(num1.begin()) == '-')
    225            {
    226                 sign = 1;
    227                 num1.pop_front();
    228            }
    229          len1 = num1.size();
    230          if(len2 == 1)
    231          {
    232             ans = Mul(num1,num2);
    233             if(sign)
    234                 ans.push_front('-');
    235          }
    236          else
    237          {
    238             for(iter= num1.begin(),i = 0; i < len1 / 2; i++,iter++)
    239             {
    240                 high.push_back(*iter);
    241             }
    242             for(;iter!=num1.end();iter++)
    243             {
    244                 low.push_back(*iter);
    245             }
    246             len = low.size();
    247             anshigh = Mul(num2,high);                   //num2分为两部分,high,low
    248             anslow = Mul(num2,low);
    249             for(i = 0; i < len; i++)
    250                 anshigh.push_back('0');
    251             ans = Add(anshigh,anslow);                    //合并结果
    252             if(sign)
    253                 ans.push_front('-');
    254          }
    255          return ans;
    256     }                                                       //如果两数位数都大于1,则都运用分治
    257     else
    258     {
    259         list<char> num1high,num1low,num2high,num2low;
    260         int flag1 = 0,flag2 = 0;
    261         if(*(num1.begin()) == '-')
    262         {
    263             flag1 = 1;
    264             num1.pop_front();
    265         }
    266         if(*(num2.begin()) == '-')
    267         {
    268             flag2 = 1;
    269             num2.pop_front();
    270         }
    271         if((flag1 == 1 && flag2 == 0)||(flag1 == 0 && flag2 == 1))  //如果有一正一负,则标记结果为负
    272         {
    273             sign = 1;
    274         }
    275         len1 = num1.size();
    276         len2 = num2.size();
    277         if(len1 == 1 || len2 == 1)                 //如果有一个数是一位数,则直接递归调用
    278         {
    279             ans = Mul(num1,num2);
    280             if(sign)
    281                 ans.push_front('-');
    282         }
    283         else
    284         {                                                //否则分治法求
    285             for(iter = num1.begin(),i = 0; i < len1 / 2; iter++,i++)
    286                 num1high.push_back(*iter);            //被乘数高位部分
    287             for( ; iter != num1.end(); iter++)
    288                 num1low.push_back(*iter);                 //被乘数低位部分
    289             for(iter = num2.begin(),i = 0; i < len2 / 2; iter++,i++)
    290                 num2high.push_back(*iter);                  //乘数高位部分
    291             for( ; iter != num2.end(); iter++)
    292                 num2low.push_back(*iter);                    //乘数低位部分
    293             int a = (len1 + 1) / 2;
    294             int b = (len2 + 1) / 2;
    295             list<char> AC,AD,BC,BD;
    296             //print(num2high);cout << endl;
    297             //print(num2low);cout << endl;
    298             AC = Mul(num1high,num2high);                  //运用X=A*10^a + B; Y= C*10^b + D;
    299             AD = Mul(num1high,num2low);                   // X*Y = AC * 10 ^(a+b) + AD *10^a + BC * 10 ^b + BD公式求
    300             BC = Mul(num1low,num2high);
    301             BD = Mul(num1low,num2low);
    302             for(i = 0; i < a + b; i++)
    303                 AC.push_back('0');
    304             for(i = 0; i < a; i++)
    305                 AD.push_back('0');
    306             for(i = 0; i < b; i++)
    307                 BC.push_back('0');
    308             ans = Add(AC,AD);
    309             ans = Add(ans,BC);
    310             ans = Add(ans,BD);                            //累加结果
    311             if(sign)
    312                 ans.push_front('-');
    313         }
    314         return ans;
    315     }
    316 }
    317 void Div(list<char> num1,list<char> num2)                 //用辗转相除求结果
    318 {
    319     list<char> ans;
    320     list<char> temp;
    321     int len1,len2,len;
    322     int i,j,k;
    323     int sign = 0;
    324     int flag1 = 0,flag2 = 0;
    325     list<char>::iterator iter;
    326     if(*(num1.begin()) == '-')
    327     {
    328         flag1 = 1;
    329         num1.pop_front();
    330     }
    331     if(*(num2.begin()) == '-')
    332     {
    333         flag2 = 1;
    334         num2.pop_front();
    335     }
    336     if((flag1 == 1 && flag2 != 1) || (flag1 == 0 && flag2 == 1))
    337         sign = 1;                                          //标记结果符号
    338     len1 = num1.size();
    339     len2 = num2.size();
    340     if(len1 < len2)                                 //如果被除数小于除法,除数为0
    341     {
    342         cout << "商是0;余数是" ;
    343         print(num2);
    344         cout << endl;
    345         return ;
    346     }
    347     else                                               //用辗转相除求结果
    348     {
    349         for(iter = num1.begin(),i = 0; i < len2 ;++i,++iter)
    350             temp.push_back(*iter);
    351         list<char> digit,res;
    352         for(j = 0; j < 10; j++)
    353         {
    354                 digit.clear();
    355                 digit.push_back(j + '0');
    356                 res = Mul(num2,digit);
    357                 res = Sub(temp,res);
    358                 if(*(res.begin()) == '-')
    359                     break;
    360         }
    361             //cout << endl;print(temp); cout << endl;
    362         j -= 1;
    363         if(j > 0)
    364         {
    365             digit.clear();
    366             digit.push_back(j + '0');
    367             temp = Sub(temp,num2);
    368             ans.push_back(j + '0');
    369         }
    370         
    371         for(;iter != num1.end();++iter)
    372         {
    373             temp.push_back(*iter);
    374             for(j = 0; j < 10; j++)
    375             {
    376                 digit.clear();
    377                 digit.push_back(j + '0');
    378                 res = Mul(num2,digit);
    379                 res = Sub(temp,res);
    380                 if(*(res.begin()) == '-')
    381                     break;
    382             }
    383             //cout << endl;print(temp); cout << endl;
    384             j -= 1;
    385             digit.clear();
    386             digit.push_back(j + '0');
    387             res = Mul(num2,digit);
    388             temp = Sub(temp,res);
    389             ans.push_back(j + '0');
    390         }
    391         if(sign)
    392             ans.push_front('-');
    393     }
    394     cout << "商是";
    395     print(ans);
    396     cout << ";余数是" ;
    397     print(temp);
    398     cout << endl;
    399     return ;
    400 }
    401 void  Root(list<char> num1)                     //求大数的平方根,用枚举算法暴力搜索算法求
    402 {
    403     list<char> ans;
    404     int len1;
    405     list<char> digit,temp;
    406     len1 = num1.size();
    407     int a = len1 / 2;                            //a是结果的最少位数
    408     int i;
    409     digit.push_back('1');
    410     ans.push_back('1');                        //从ans=10 ^ a 开始搜索
    411     for(i = 0; i < a - 1; i++)
    412         ans.push_back('0');
    413     while(true)                                  //搜到则结束
    414     {
    415         temp = Mul(ans,ans);
    416         temp = Sub(num1,temp);
    417         if(*(temp.begin()) == '-')                      //如果当前ans的平方大于num1,则得结果
    418             break;
    419         ans = Add(ans,digit);
    420     }
    421     ans = Sub(ans,digit);
    422     print(ans);
    423     cout << endl;
    424 }
    425 list<char> translate(string input)
    426 {
    427     list<char> res;
    428     int len = input.length();
    429     for(int i = 0; i < len; i++)
    430         res.push_back(input[i]);
    431     return res;
    432 }
    433 void print(list<char> ans)
    434 {
    435     list<char>::iterator iter;
    436     int flag = 1;
    437     iter = ans.begin();
    438     if(*iter == '-')
    439      {
    440         cout << *iter;
    441         iter++;
    442      }
    443     for(;iter != ans.end(); ++iter)
    444     {
    445         if(*iter == '0' && flag)
    446             continue;
    447             //cout << (*iter);
    448         else
    449         {
    450             flag = 0;
    451             cout << (*iter);
    452         }
    453     }
    454     if( flag == 1)
    455         cout << 0 ;;
    456     //cout << endl;
    457 }
    458 int main()
    459 {
    460     char choice;         //选择要进行的运算
    461     list<char> num1;
    462     list<char> num2;
    463     list<char> res;
    464     string input;
    465     while(true)
    466     {
    467         cout << endl;
    468         printhelp();
    469         cin >> choice;
    470         switch(choice)
    471         {
    472             case '1':                      //如果选择加法运算
    473                 cout << "请输入第一个数" << endl;
    474                 cin >> input;
    475                 num1 = translate(input);
    476                 cout << "请输入第二个数" << endl;
    477                 cin >> input;
    478                 num2 = translate(input);
    479                 res = Add(num1,num2);
    480                 print(num1);
    481                 cout << " + " ;
    482                 print(num2);
    483                 cout << " = ";
    484                 print(res);
    485                 cout << endl;
    486                 break;
    487             case '2':                    //选择减法运算
    488                 cout << "请输入第一个数" << endl;
    489                 cin >> input;
    490                 num1 = translate(input);
    491                 cout << "请输入第二个数" << endl;
    492                 cin >> input;
    493                 num2 = translate(input);
    494                 res = Sub(num1,num2);
    495                 print(num1);
    496                 cout <<" - " ;
    497                 print(num2);
    498                 cout << " = ";
    499                 print(res);
    500                 cout << endl;
    501                 break;
    502             case '3':                  //选择乘法运算
    503                 cout << "请输入第一个数" << endl;
    504                 cin >> input;
    505                 num1 = translate(input);
    506                 cout << "请输入第二个数" << endl;
    507                 cin >> input;
    508                 num2 = translate(input);
    509                 res = Mul(num1,num2);
    510                 print(num1);
    511                 cout <<" * " ;
    512                 print(num2);
    513                 cout << " = ";
    514                 print(res);
    515                 cout << endl;
    516                 break;
    517             case '4':                      //选择除法运算
    518                 cout << "请输入第一个数" << endl;
    519                 cin >> input;
    520                 num1 = translate(input);
    521                 cout << "请输入第二个数" << endl;
    522                 cin >> input;
    523                 num2 = translate(input);
    524                 print(num1);
    525                 cout << " / " ;
    526                 print(num2);
    527                 cout << " = ";
    528                 if(num2.size() == 1 && (*(num2.begin()) == '0'))
    529                 {
    530                     cout << "divided zero error" << endl;
    531                     break;
    532                 }
    533                 Div(num1,num2);
    534                 //print(res);
    535                 cout << endl;
    536                 break;
    537             case '5':                         //选择求根运算
    538                 cout << "请输入第一个数" << endl;
    539                 cin >> input;
    540                 num1 = translate(input);
    541                 if(*(num1.begin()) == '-')
    542                 {
    543                     cout << "负数没有实数平方根" << endl;
    544                     break;
    545                 }
    546                 Root(num1);
    547                 break;
    548             case '6':
    549                 return 0;
    550             default:
    551                   break;
    552         }
    553     }
    554 }
    View Code
  • 相关阅读:
    [转载]Oracle 11g R1中资本管理器增强(2)
    [转载]Oracle监听器安装与设置(2)
    [转载]Oracle 11g R1中资源管理器加强(3)
    [转载]Oracle能否吸收领跑数据库市场?(2)
    [转载]怎样高效删除Oracle数据库中的反双数据
    [转载]Oracle 11g R1下的主动内存处置惩罚(1)
    [转载]Oracle假造公用数据控制设备使用
    [转载]Oracle可否担当领跑数据库市场?(1)
    [转载]将oracle 9i备份文件导入oracle 8i的方式简介
    OpenSuSE 11.1内行装置教程(贴图版)
  • 原文地址:https://www.cnblogs.com/liugl7/p/4925467.html
Copyright © 2011-2022 走看看