Thursday, May 16, 2013

大数相乘string multiplication C

面试题给的是C string,那就写C吧。基本上就是模拟实际的乘法,因为数值很大存不了int,很自然要用string来存了。考虑进位的需要,结果应该是最多m+n位,再加上末位的'\0'字符,应该给结果分配m+n+1 byte的空间。此外还要考虑负数,不过我char array不熟,折腾了很久,就懒得再加这个case了。。
从写这个code,学到了char[]和char *的区别,最大的不同就是如果char *指向的是string literal, 内容不可更改,所以这里传入参数应该是由char[]定义的。
  1. //assume that no negative integers are involved.  
  2. //reverse a c string  
  3. void reverse(char *c, int start, int end){  
  4.     
  5.   while(start < end){  
  6.   
  7.      char tmp = c[start];  
  8.   
  9.      c[start++] = c[end];  
  10.   
  11.      c[end--] = tmp;      
  12.   
  13.  }   
  14. }  
  15.   
  16. char* MultiplyString(char *a,char *b){  
  17.   
  18.    int m = strlen(a), n = strlen(b);  
  19.    //one extra position for carry, another one extra position for '\0'  
  20.    char *c = new char[m+n+1];  
  21.    memset(c, '0', m+n);  
  22.    reverse(a,0,m-1);  
  23.    reverse(b,0,n-1);  
  24.    int carry;  
  25.    //for each position in b, do the multiplication of b[i]*a,update corresponding positions in result c.  
  26.    for(int i = 0; i < n; i++){  
  27.   
  28.      carry = 0;  
  29.       
  30.      for(int j = 0; j < m; j++){  
  31.   
  32.        int prod = (b[i] - '0')*(a[j] - '0') + carry + (c[i+j] - '0');  
  33.    
  34.        carry = prod/10;  
  35.   
  36.        c[i+j] = prod%10 + '0';  
  37.      }  
  38.    }  
  39.    //deal with the highest position's carry  
  40.    if(carry != 0) {   
  41.       c[m+n-1] = '0' + carry;   
  42.       reverse(c,0,m+n-1);  
  43.     }  
  44.   
  45.    else {  
  46.       c[m+n-1] = '\0';  
  47.       reverse(c,0,m+n-2);  
  48.    }  
  49.   
  50.    return c;   
  51. }  
此外无意间发现一个有趣的swap方法,利用a^a ^b=b,可以不用额外tmp存中间值的:

swap(a,b):
  a = a^b
  b = b^a
  a = a^b

No comments:

Post a Comment