C语言大数运算-乘除法篇「建议收藏」

C语言大数运算-乘除法篇「建议收藏」前言:这是第三篇博客,也是一次介绍二个计算的博客,可能难度会比前两篇博客大一点,所以建议对于初学者来说一定要看完我的前两篇博客再来看本篇博客,关于本次实验的环境,和思想在第一篇博客已经简单介绍过了,所以不再赘述,我会先介绍大数的乘法载介绍大数的除法,乘法的难点在于要使用一个嵌套循环,除法的难点在于一个字使用符串比较方法的技巧,本次还是会将算法都写成函数,然后在main()函数中调用,原因是在第四

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

前言:
这是第三篇博客,也是一次介绍二个计算的博客,可能难度会比前两篇博客大一点,所以建议对于初学者来说一定要看完我的前两篇博客再来看本篇博客,关于本次实验的环境,和思想在第一篇博客已经简单介绍过了,所以不再赘述,我会先介绍大数的乘法载介绍大数的除法,乘法的难点在于要使用一个嵌套循环,除法的难点在于一个字使用符串比较方法的技巧,本次还是会将算法都写成函数,然后在main()函数中调用,原因是在第四篇我们要将整个大数运算的方法做成自己的一个库文件,可以供自己或他人使用。

大数乘法:
由于乘法可以互换所以对于输入的数字没有限制条件,计算方法还是模仿手工算法,由被乘数的低位开始和乘数的每一位相乘并且要将大于9的十位数向前进一位,存在3个问题需要我们解决。

问题:
1 我们要用多大的数组存储结果?
2 要使用嵌套循环吗?
3 如何在计算的过程中保证进位?

其实问题也很好解决,前两个问题都可以看出答案,最后一个问题和前两篇博客的进位问题很相似,所以简单的说明后再看注释的代码是很好懂的。
1 二个数相乘最大的位数是两个乘数的位数之和。
2 很明显由于乘法的特性使用嵌套循环很合适。
3 在大数加减中执行完毕后再对存储结果的result数组进行一次进位,但在乘法中我们需要每执行一趟就要对数组进行进位的处理。

实现:
下面是全面的含有注释的代码。

  1 //#include"big.h"
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 char * bigmul(char *m,int lena,char *f,int lenb){  //乘法运算函数。
  6    int i,j,k,lensum,tmp_result,carry,num='0';
  7    lensum=lena+lenb;                               //确定结果数组的长度。
  8    for(i=0;i<lena;i++){                            //将ASCII码转为对应的数字存储。
  9       m[i]=m[i]-num;
 10    }
 11    for(i=0;i<lenb;i++){
 12       f[i]=f[i]-num;
 13    }
 14    char *result,final[BUFSIZ];
 15    result=(char*)calloc(lensum,1);
 16    for(i=0;i<lenb;i++){                      //为被乘数作一趟乘法。
 17       for(j=0;j<lena;j++){
 18          tmp_result=f[lenb-i-1]*m[lena-j-1];
 19          result[j+i]+=tmp_result;
 20       }
 21       for(k=0;k<=j+i-1;k++){                 //每作一趟乘法整理一次结果数组。
 22          if(result[k]>9){
 23             carry=result[k]/10;
 24             result[k]=result[k]%10;
 25             result[k+1] += carry;
 26          }
 27       }
 28    }
 29    j=0;
 30    if(result[lensum-1]!=0){                  //去除前导零将结果整理到final数组中。
 31       final[j]=result[lensum-1]+num;
 32       j++;
 33    }
 34    for(i=lensum-2;i>=0;i--){
 35       final[j++]=result[i]+num;
 36    }
 37    result=final;                             //将指针指向final数组并返回该指针。 
 38    return result;
 39 }
 40 int main(){                                                 //利用main测试方法,用puts打印结果。 
 41    int lena,lenb;
 42    char *result,sa[BUFSIZ],sb[BUFSIZ];
 43    scanf("%s",sa);
 44    scanf("%s",sb);
 45    lena=strlen(sa);
 46    lenb=strlen(sb);
 47    result=bigmul(sa,lena,sb,lenb);
 48    puts(result);
 49 
 50 }

下面是大数除法。

前言:
大数除法的难点在于思考算法,可以用连续的减法来实现,举个简单了例子:32/2可以用32连续减去2每减一次i加一,当差小于被减数时停止。i即为商,由于我们前面实现了大数减法所以用该方法可以实现,但是有一个问题就是如果用一亿除以一那么就需要执行一亿次,况且我们做的是大数数算,输入100位以上的数也都是有可能的,那么计算的时间就是几天,几年,几万年都有可能。所以只有模仿手工的方法,从高位开始计算。32/2从高位先用3-2只能减1次,将余数保留变成12/2,可以减6次,从而得到结果16极大的降低了循环减的次数。

大数除法:
有很多问题大多都是的我们前面遇到的问题,例如结果数组的位数,对数组的整理进位问题,嵌套循环和乘法相同按趟执行,既然是相似的问题我就不再说了。

注意:
除法对数据有限制不能分母为零,分母为零没有意义,不能用小数除以大数,因为小数除以大数本质还是大数除以小数结果加个分之一就可以了。
返回的结果是保存商的数组的指针,不包含余数。

实现:
下面是完整的含有注释的代码,如果想判断输入,或输入余数,可自行修改代码。

  1 //#include"big.h"
  2 #include<stdio.h>
  3 #include<string.h>
  4 char diva[BUFSIZ],divb[BUFSIZ];
  5 char result_tmp[BUFSIZ];
  6 char final[BUFSIZ];
  7 char * bigdiv(char *diva,int lena,char *divb,int lenb){        //大数除法函数。
  8     int i,j,k;
  9     char  * result;
 10 /* if((lena<lenb||lena==lenb)&&strcmp(diva,divb)<0){ //去除了以小除大的判断 11 printf("0 余数=");//求余数 12 for(i=0; i<lena; i++) 13 printf("%d",diva[i]-'0'); 14 printf("\n"); 15 return result; 16 } 17 */
 18             k=0;
 19             while(1){                        //死循环只有当lena和lenb相等时跳出循环,因为会不断的在divb数组前加0所以该数组的长度,
 20                                              //会不断的变化当两者相等时说明已经无法在作减法。
 21                 result_tmp[k]=0;
 22                 while(strcmp(diva,divb)>=0){ //用字符串比较的方法是一个亮点,很巧妙。因为strcmp()比较的方式是从前到后依次比较 
 23                  int i=0,j;                  //如果相等则向后移动一位一旦发现不等则立即返回忽略后面的所有数据。
 24                      while(1){
 25                         if(diva[i]=='0') i++;//去除diva高位前面的0
 26                         else{
 27                            j=i;              //去除divb高位填充的0
 28                          break;  
 29                         }  
 30                }
 31     
 32                for(; i<lenb; i++)            //作减法
 33                diva[i]=diva[i]-divb[i]+'0';
 34                for(i=lenb-1; i>j; i--)       //每作一组减法就整理数组,这种整理数组在前几篇中都有使用。
 35                if(diva[i]<'0'){              //不过在这里不是整理结果数组而是diva数组,结果保存在a数组中不用整理
 36                   diva[i]+=10;;
 37                   diva[i-1]--;
 38                }
 39                     result_tmp[k]++;
 40 
 41                }
 42                   k++;
 43                   if(lena==lenb)   break;
 44                   for(i=lenb-1; i>=0; i--)   //将divb中的元素先后移位,同时扩大divb长度并且在divb前端补一位0。
 45                     divb[i+1]=divb[i];
 46                   divb[0]='0';               //由于数组后移所以divb[0]每次移动后都为空,所以每次用0补齐。
 47                   lenb++;
 48                   divb[lenb]='\0';           //在结尾加上字符串的结束标记。
 49             }
 50             i=0;j=0;
 51             while(result_tmp[i]==0) i++;
 52             for(; i<k; i++){
 53                 final[j++]=result_tmp[i]+'0';
 54 
 55             }
 56             result=final;
 57 /* 58 printf(" 余数="); 59 j=0;//求余数 60 while(diva[j]=='0') j++; 61 if(j==lena) 62 { 63 printf("0\n"); 64 continue; 65 } 66 for(; j<n; j++) 67 printf("%d",diva[j]-'0'); 68 printf("\n"); 69 */
 70 
 71             return result;
 72 
 73 }
 74 int main(){                                                 //利用main测试方法,用puts打印结果。 
 75    int lena,lenb;
 76    char *result,sa[BUFSIZ],sb[BUFSIZ];
 77    scanf("%s",sa);
 78    scanf("%s",sb);
 79    lena=strlen(sa);
 80    lenb=strlen(sb);
 81    result=bigdiv(sa,lena,sb,lenb);
 82    puts(result);
 83 
 84 }

所有的运算到此完结最后一篇做一个大数运算库,有时间我会把库放到github如果以后有时间我会做些优化并且加入对浮点的支持。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185093.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java冒泡排序代码_Java冒泡排序

    java冒泡排序代码_Java冒泡排序一、冒泡排序:利用冒泡排序对数组进行排序二、基本概念:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2…

    2022年7月8日
    12
  • Feign原理_feign源码

    Feign原理_feign源码feign是一种http客户端,可以让你通过简单地注解的方式,调用其他的http服务。feign提供的注解是@FeignClient,一直很好奇feign是怎么生效的,今天跟着代码一块看一下。要想使用feign的话,首先要在项目中打上@EnableFeignClients注解,从代码中可以看到,@EnableFeignClients通过@Import注解引入了Fei…

    2022年10月4日
    0
  • 解读windows认证

    0x00前言dll劫持的近期忙,没时间写,先给大家写个windows认证的水文。0x01windows认证协议windows上的认证大致分为本地认证,ntlm协议,和Kerberos协议。

    2021年12月11日
    57
  • maven使用入门[通俗易懂]

    maven使用入门[通俗易懂]maven面临的问题一个项目就是一个工程。如果项目非常大,最好是每一个模块对应一个工程。借助maven可以将一个项目拆分成多个工程项目中需要的jar必须要手动”复制”,”粘贴”到WEB-INF/lib目录下,带来的问题是:同样的jar包文件重复出现在不同的项目工程中,浪费空间。maven可以将jar仅仅保存在”仓库”中,有需要使用的工程”引用”这个文件接口,并不需要真的把jar包复制过来jar包需要别人替我们准备好,或到官网下载。不同技术的官网提供jar包下载的形式是五花八门的,有些技术的官网就是

    2022年8月8日
    3
  • 新人如何入行3D游戏建模

    新人如何入行3D游戏建模所有行业都是一样的,没有什么容易的,只不过这一行是偏向于技术的,一个有好的建模师月薪10k+是很常见的,这个需要有自己刻苦学习的成果。游戏建模前景在游戏模型行业,你基本不用担心找不到工作,因为游戏模型师人才缺口非常大。举个例子:游戏制作公司的人员配比大多数是这样的:比如100人的三维制作组,可能有60人在做模型贴图,10个人在K动画。只要你保证技能在手,一定是抢手的人才。在几年前游戏建模这个行业不仅仅缺人才,甚至连新手都非常稀缺,那个时候公司愿意招聘实习生,培养他们然后给公司干活,但是工资一定不会给开的很

    2022年5月12日
    47
  • html echarts饼状图_echarts环形图

    html echarts饼状图_echarts环形图ECharts旭日图旭日图(Sunburst)由多层的环形图组成,在数据结构上,内圈是外圈的父节点。因此,它既能像饼图一样表现局部和整体的占比,又能像矩形树图一样表现层级关系。ECharts创建旭日图很简单,只需要在series配置项中声明类型为sunburst即可,data数据结构以树形结构声明,看下一个简单的实例:实例varoption={series:{type:’s…

    2022年9月26日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号