面试100题系列之13大数的四则运算

本文详细介绍了一种使用字符串存储大数并实现加、减、乘运算的方法。通过逆向字符串简化了计算过程,并针对不同情况(如负数)进行了特殊处理。此外,还提供了一个完整的示例程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面试100题系列之13大数的四则运算

分类: 面试笔试 大数 字符串   118人阅读  评论(0)  收藏  举报

关于大数的四则运算,我想网上有很多方法,感觉通用性不强,然后呢,功能不强大,效率不高~~问题多多啊~然后呢,大数这个东西又经常碰到,所以呢,我一咬牙,写了一个比较完整的,花了我一下午的时间啊,不过除法还没有写,有时间再写吧。最近事情太多了,写了之后再补上。
OK,说一下我的思路。首先这里用字符串存数据,这个地球人都知道。第0位是高位。当我们算加减的时候需要从低位开始算起。所以我一开始的思路是将字符串反转一下,然后开始计算,这样也不会担心最后有进位或者借位了,计算好之后再反转回来。OK,这样我为了算一个加法,反转四次啊!!!代价有点大,不能接受。
怎么样能既方便运算又不用反转那么多呢?要是只反转一次就好了。如果把结果的数组指针传进去,算的时候分别从两个字符串尾部开始遍历,将结果从下标0开始一次存入结果数组。最后把结果数组反转一下就可以了。好了,加减搞定了。
对于乘法,str1[i]与str2[j]乘的结果放在结果数组的i+j位,这个结论怎么来的呢?其实也就是我们写的竖式啦,写写看~这里需要一个临时的int数组arr来存放乘的结果,arr[i+j]存放所有满足条件的i和j的元素之和。然后将arr里面的数据拆分到ans数组里面就可以了。
最后说明一下,每个函数加入一个nMaxLen的参数是保证计算的结果不会溢出,也就是不会超过ans数组的最大容量,这里我采用的办法是返回一个NULL,但是这样可能与一些函数(比如说printf)嵌套使用的时候就不是很方便。这里其实可以将返回NULL的操作替换成往结果数组里面打印相应的字符串,来表明错误。
路过的大爷们,转载请注明出处:http://blog.youkuaiyun.com/kay_zhyu/article/details/8877032哦~~小女子万分感激~~~
核心代码如下,这里支持负数运算哦,欢迎大家找Bug:

[cpp]  view plain copy
  1. //两个字符串相加  
  2. //str1和str2是加数,ans是结果数组,nMaxLen是结果数组的最大空间  
  3. char* Add(charconst str1, charconst str2, char *ans, int nMaxLen)  
  4. {  
  5.     //一些参数检验  
  6.     if(!str1 || !str2 || !ans || nMaxLen < 1)  
  7.         return NULL;  
  8.     //保证是两个整数相加  
  9.     if(str1[0] == '-' && str2[0] == '-')//负加负  
  10.     {  
  11.         ans[0] = '-';  
  12.         if(Add(str1 + 1, str2 + 1, ans + 1, nMaxLen - 1))  
  13.             return ans;  
  14.         else  
  15.             return NULL;  
  16.     }  
  17.     else if(str1[0] == '-')//一正一负  
  18.     {  
  19.         return Minus(str2, str1 + 1, ans, nMaxLen);  
  20.     }  
  21.     else if(str2[0] == '-')  
  22.     {  
  23.         return Minus(str1, str2 + 1, ans, nMaxLen);  
  24.     }  
  25.     int nLen1 = strlen(str1);  
  26.     if(nMaxLen < nLen1)  
  27.         return NULL;  
  28.     int nLen2 = strlen(str2);  
  29.     if(nMaxLen < nLen2)  
  30.         return NULL;  
  31.     int i,j,k;  
  32.     int a,b,carry;  
  33.     carry = 0;  
  34.     //加公共部分  
  35.     for(i = nLen1 - 1, j = nLen2 - 1, k = 0;  
  36.         (i >= 0 && j >= 0 && k < nMaxLen); --i,--j,++k)  
  37.     {  
  38.         a = str1[i] - '0';  
  39.         b = str2[j] - '0';  
  40.         ans[k] = (a + b + carry) % 10 + '0';  
  41.         carry = (a + b + carry) / 10;  
  42.     }  
  43.     //加str1的多余部分  
  44.     for( ; (i >= 0 && k < nMaxLen); --i, ++k)  
  45.     {  
  46.         a = str1[i] - '0';  
  47.         ans[k] = (a + carry) % 10 + '0';  
  48.         carry = (a + carry) / 10;  
  49.     }  
  50.     //加str2的多余部分  
  51.     for( ; (j >= 0 && k < nMaxLen); --j, ++k)  
  52.     {  
  53.         b = str1[j] - '0';  
  54.         ans[k] = (b + carry) % 10 + '0';  
  55.         carry = (b + carry) / 10;  
  56.     }  
  57.     if(carry > 0 && k < nMaxLen)  
  58.         ans[k++] = carry + '0';  
  59.     //结果的越界检查  
  60.     if(k >= nMaxLen)  
  61.         return NULL;  
  62.     //加上结束标记  
  63.     ans[k] = '\0';  
  64.     Invert(ans, k);  
  65.     return ans;  
  66. }  
  67. //两个大数相减  
  68. //str1-str2,ans表示结果,nMaxLen表示ans的最大长度  
  69. char* Minus(charconst str1, char * const str2, char *ans, int nMaxLen)  
  70. {  
  71.     //一些参数检验  
  72.     if(!str1 || !str2 || !ans || nMaxLen < 1)  
  73.         return NULL;  
  74.     //保证是正数减正数  
  75.     if(str1[0] != '-' && str2[0] == '-')//正减负  
  76.         return Add(str1, str2 + 1, ans, nMaxLen);  
  77.     else if(str1[0] == '-' && str2[0] == '-')//负减负  
  78.         return Minus(str2 + 1, str1 + 1, ans, nMaxLen);  
  79.     else if(str1[0] == '-' && str2[0] != '-')//负减正  
  80.     {  
  81.         ans[0] = '-';  
  82.         if(Add(str1 + 1, str2, ans + 1, nMaxLen - 1))  
  83.             return ans;  
  84.         else  
  85.             return NULL;  
  86.     }  
  87.     //保证str1大于str2  
  88.     int nLen1 = strlen(str1);  
  89.     if(nMaxLen < nLen1)  
  90.         return NULL;  
  91.     int nLen2 = strlen(str2);  
  92.     if(nMaxLen < nLen2)  
  93.         return NULL;  
  94.     if(nLen1 < nLen2 || (nLen1 == nLen2 && str1[0] < str2[0]))  
  95.     {  
  96.         ans[0] = '-';  
  97.         if(Minus(str2, str1, ans + 1, nMaxLen - 1))  
  98.             return ans;  
  99.         else  
  100.             return NULL;  
  101.     }  
  102.     int i,j,k;  
  103.     int a,b,carry;  
  104.     bool IsPos = true;  
  105.     carry = 0;  
  106.     //减去公共的部分,str1大于str2  
  107.     for(i = nLen1 - 1, j = nLen2 - 1, k = 0;  
  108.         (i >= 0 && j >= 0 && k < nMaxLen); --i,--j,++k)  
  109.     {  
  110.         a = str1[i] - '0' - carry;  
  111.         b = str2[j] - '0';  
  112.         if(a < b)  
  113.         {  
  114.             a += 10;  
  115.             carry = 1;  
  116.         }  
  117.         else  
  118.             carry = 0;  
  119.         ans[k] = a - b + '0';  
  120.     }  
  121.     //得到str1剩余的部分  
  122.     for(; (i >= 0 && k < nMaxLen); --i,++k)  
  123.     {  
  124.         a = str1[i] - '0' - carry;  
  125.         if(a < carry)  
  126.         {  
  127.             a += 10;  
  128.             carry = 1;  
  129.         }  
  130.         else  
  131.             carry = 0;  
  132.         ans[k] = a + '0';  
  133.     }  
  134.     if(carry > 0 && k < nMaxLen)  
  135.         ans[k++] = '-';  
  136.     if(k >= nMaxLen)  
  137.         return NULL;  
  138.     ans[k] = '\0';  
  139.     Invert(ans, k);  
  140.     return ans;  
  141. }  
  142. //大数乘法  
  143. //str1*str2,ans是结果,nMaxLen是ans的最大容量  
  144. char *Mutiply(charconst str1, charconst str2, char *ans, int nMaxLen)  
  145. {  
  146.     if(!str1 || !str2 || !ans || nMaxLen < 1)  
  147.         return NULL;  
  148.     //保证是两个正数相乘  
  149.     if(str1[0] == '-' && str2[0] == '-')  
  150.         return Mutiply(str1 + 1, str2 + 1, ans, nMaxLen);  
  151.     else if(str1[0] == '-')  
  152.     {  
  153.         ans[0] = '-';  
  154.         if(Mutiply(str1 + 1, str2, ans + 1, nMaxLen))  
  155.             return ans;  
  156.         else  
  157.             return NULL;  
  158.     }  
  159.     else if(str2[0] == '-')  
  160.     {  
  161.         ans[0] = '-';  
  162.         if(Mutiply(str1, str2 + 1, ans + 1, nMaxLen))  
  163.             return ans;  
  164.         else  
  165.             return NULL;  
  166.     }  
  167.     int nLen1 = strlen(str1);  
  168.     int nLen2 = strlen(str2);  
  169.     if(nMaxLen < nLen1 + nLen2 - 1)//内存不够,返回  
  170.         return NULL;  
  171.     int *arr = (int *)malloc((nLen1 + nLen2 + 1)*sizeof(int));  
  172.     if(!arr)//内存申请失败,返回  
  173.         return NULL;  
  174.     memset(arr, 0, (nLen1 + nLen2 + 1)*sizeof(int));  
  175.     int i,j;  
  176.     for(i = 0; i < nLen1; ++i)  
  177.     {  
  178.         for(j = 0; j < nLen2; ++j)  
  179.         {  
  180.             arr[i+j] += (str1[i] - '0') * (str2[j] - '0');  
  181.         }  
  182.     }  
  183.     int k,carry;  
  184.     carry = 0;  
  185.     //乘积的结果转移到ans中  
  186.     for(k = 0, i = nLen1 + nLen2 - 2; i >= 0 && k < nMaxLen; --i,++k)  
  187.     {  
  188.         ans[k] = (arr[i] + carry) % 10 + '0';  
  189.         carry = (arr[i] + carry) / 10;  
  190.     }  
  191.     free(arr);//释放辅助内存  
  192.     arr = NULL;  
  193.     while(carry > 0 && k < nMaxLen)  
  194.     {  
  195.         ans[k++] = carry % 10 + '0';  
  196.         carry /= 10;  
  197.     }  
  198.     //检查是否溢出  
  199.     if(k > nMaxLen)  
  200.         return NULL;  
  201.     ans[k] = '\0';  
  202.     Invert(ans, k);  
  203.     return ans;  
  204. }  

照旧,给出辅助函数和变量定义,以及main函数的调用,不需要者可以pass~~~~

[cpp]  view plain copy
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<malloc.h>  
  4. char* Add(charconst str1, charconst str2, char *ans, int nMaxLen);  
  5. char* Minus(charconst str1, char * const str2, char *ans, int nMaxLen);  
  6. //反转字符串  
  7. void Invert(char *str, int nLen)  
  8. {  
  9.     if(!str || nLen < 1)  
  10.         return;  
  11.     char temp;  
  12.     for(int i = 0; i < nLen>>1; ++i)  
  13.     {  
  14.         temp = str[i];  
  15.         str[i] = str[nLen - 1 - i];  
  16.         str[nLen - 1 - i] = temp;  
  17.     }  
  18. }  
  19. int main()  
  20. {  
  21.     const int N = 50;  
  22.     char str1[N];  
  23.     char str2[N];  
  24.     char ans[N];  
  25.     char *p;  
  26.     while(scanf("%s %s", str1, str2) != EOF)  
  27.     {  
  28.         p = Add(str1, str2, ans, N);//加  
  29.         if(p)  
  30.             puts(p);  
  31.         p = Minus(str1, str2, ans, N);//减  
  32.         if(p)  
  33.             puts(p);  
  34.         p = Mutiply(str1, str2, ans, N);//乘  
  35.         if(p)  
  36.             puts(p);      
  37.     }  
  38.     return 0;  
  39. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值