大数问题:用字符串解决大数相加和相乘。

 

大数问题:用字符串解决大数相加和相乘。

分类: 数据结构和算法   4349人阅读  评论(5)  收藏  举报

在ACM的题目中经常会遇到大数相加和相乘的问题,在有些公司的面试题中也有暗含要用大数才能解决的问题。比如:输入三个整数,写一个程序判断这个三个整数能否构成一个直角三角形。此题算法很简单,但是却暗含着结果可能溢出的问题。如果不会用大数,此题就无法给出完美的答案。

下面给出大数的乘法和加法算法:

1、加法:

//  assume m is bigger than n.
char *  add( char   * a,  char   * b,  int  m,  int  n)
{
    
//  为结果分配内存空间。
     char   * =  ( char * )malloc((m  +   2 ) *   sizeof ( char ));
    memset(c, 
0 , (m  +   2 *   sizeof ( char ));
    
//  将字符(0 + 0x30 到 9 + 0x30)转换为数字(0到9)进行计算。
     for  ( int  i  =  m, j  =  n  -   1 ; j  >=   0 -- i,  -- j)
        c[i] 
+=  (b[j]  -   0x30 );
    
for  ( int  i  =  m, j  =  m  -   1 ; j  >=   0 -- i,  -- j)
    {
        c[i] 
+=  (a[j]  -   0x30 );
        
if  (c[i]  >   9 )
        {
            c[i 
-   1 +=   1 ;
            c[i] 
-=   10 ;
        }
    }
    
//  将由纯数字组成的结果转换为字符串,并去除首部可能还存在的零。
   c[m + 1] = '/0';
     for  ( int  i  =   0 ; i  !=  m  +   1 ++ i)
        c[i] 
+=   0x30 ;
    
if  (c[ 0 ==   0x30 )
        
for  ( int  i  =   0 ; c[i] != '/0';  ++ i)
            c[i] 
=  c[i  +   1 ];
    
//  返回结果所在内存单元的首地址。
     return  c;
}

2、乘法:

//  assume m is bigger than n.
char *  mult( char   * a,  char   * b,  int  m,  int  n)
{
    
//  为结果分配内存空间。
     char   * =  ( char * )malloc((m  +  n  +   1 *   sizeof ( char ));
    memset(c, 
0 , (m  +  n  +   1 *   sizeof ( char ));

    
//  将字符(0 + 0x30 到 9 + 0x30)转换为数字(0到9)进行计算。
     for  ( int  i  =  m  -   1 , r  =  m  +  n  -   1 ; i  >=   0 -- i,  -- r)
    {
        
for  ( int  j  =  n  -   1 , k  =  r; j  >=   0 -- j,  -- k)
        {
            c[k] 
+=  (a[i]  -   0x30 *  (b[j]  -   0x30 );
            
int  tmp  =  c[k]  /   10 ;
            
if  (tmp  >   1 )
            {
                c[k 
-   1 +=  tmp;
                c[k] 
-=  tmp  *   10 ;
            }
        }
    }

    
//  将由纯数字组成的结果转换为字符串,并去除首部可能还存在的零。
    c[m + n] = '/0';
    
for  ( int  i  =   0 ; i  !=  m  +  n;  ++ i)
        c[i] 
+=   0x30 ;
     if  (c[ 0 ==   0x30 )
        
for  ( int  i  =   0 ;  c[i] != '/0';  ++ i)
            c[i] 
=  c[i  +   1 ];

    
//  返回结果所在内存单元的首地址。
     return  c;
}



[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <assert.h>  
  5.   
  6. // assume m is bigger than n.  
  7. char* mult(char *a, char *b, int m, int n) {  
  8.     int g = m + n;  
  9.     // 为结果分配内存空间。  
  10.     char *c = (char*)malloc(g * sizeof(char));  
  11.     memset(c, 0, g * sizeof(char));  
  12.   
  13.     c[g - 1] = '\0';  
  14.     // 将字符(0 + 0x30 到 9 + 0x30)转换为数字(0到9)进行计算。  
  15.     for (int i = m - 1, r = g - 2; i >= 0; --i, --r) {  
  16.         for (int j = n - 1, k = r; j >= 0; --j, --k) {  
  17.             c[k] += (a[i] - 0x30) * (b[j] - 0x30);  
  18.             int tmp = c[k] / 10;  
  19.             if (tmp >= 1) {  
  20.                 assert(k - 1 >= 0);  
  21.                 c[k - 1] += tmp;  
  22.                 c[k] -= tmp * 10;  
  23.             }  
  24.         }  
  25.     }  
  26.   
  27.     // 将由纯数字组成的结果转换为字符串,并去除首部可能还存在的零。  
  28.     for (int i = 0; i != g - 1; ++i)  
  29.         c[i] += 0x30;  
  30.     if (c[0] == 0x30)  
  31.         for (int i = 0; c[i] != '\0'; ++i)  
  32.             c[i] = c[i + 1];  
  33.   
  34.     // 返回结果所在内存单元的首地址。  
  35.     return c;  
  36. }  
  37.   
  38. void test(char* a, char* b) {  
  39.     for (int i = 0; a[i] != '\0'; ++i) {  
  40.         if (a[i] != b[i]) {  
  41.             printf("%d %c %c\n", i, a[i], b[i]);  
  42.         }  
  43.         assert(a[i] == b[i]);  
  44.     }  
  45. }  
  46.   
  47. int main() {  
  48.     char a[1024] = "123";  
  49.     char b[1024] = "1";  
  50.     printf("123 * 1\n");  
  51.     char* c = mult(a, b, 3, 1);  
  52.     test(c, "123");  
  53.     free(c);  
  54.   
  55.     strcpy(b, "12");  
  56.     printf("123 * 12\n");  
  57.     c = mult(a, b, 3, 2);  
  58.     test(c, "1476");  
  59.     free(c);  
  60.   
  61.     strcpy(b, "123");  
  62.     printf("123 * 123\n");  
  63.     c = mult(a, b, 3, 3);  
  64.     test(c, "15129");  
  65.     free(c);  
  66.   
  67.     strcpy(a, "123456789123456789");  
  68.     strcpy(b, "123456789123456789");  
  69.     printf("123456789123456789 * 123456789123456789\n");  
  70.     c = mult(a, b, 18, 18);  
  71.     test(c, "15241578780673678515622620750190521");  
  72.     free(c);  
  73.   
  74.     strcpy(a, "123456789123456789");  
  75.     strcpy(b, "12345678912345678");  
  76.     printf("123456789123456789 * 12345678912345678\n");  
  77.     c = mult(a, b, 18, 17);  
  78.     test(c, "1524157878067367740451151863907942");  
  79.     free(c);  
  80.   
  81.     strcpy(a, "123456789123456789");  
  82.     strcpy(b, "1234567891234567");  
  83.     printf("123456789123456789 * 1234567891234567\n");  
  84.     c = mult(a, b, 18, 16);  
  85.     test(c, "152415787806736675279683887625363");  
  86.     free(c);  
  87.   
  88.     return 0;  
  89. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值