C语言大数运算-乘除法篇
前言:
这是第三篇博客,也是一次介绍二个计算的博客,可能难度会比前两篇博客大一点,所以建议对于初学者来说一定要看完我的前两篇博客再来看本篇博客,关于本次实验的环境,和思想在第一篇博客已经简单介绍过了,所以不再赘述,我会先介绍大数的乘法载介绍大数的除法,乘法的难点在于要使用一个嵌套循环,除法的难点在于一个字使用符串比较方法的技巧,本次还是会将算法都写成函数,然后在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高位前面的026 else{27 j=i; //去除divb高位填充的028 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如果以后有时间我会做些优化并且加入对浮点的支持。
C语言大数运算-乘除法篇相关推荐
- c语言赋值运算与除法运算顺序,C语言运算符的优先级和结合律
如果一个表达式包含两个或两个以上的运算符,那么操作数的结合方式将决定这个表达式的结果.为了简便,我们把包含两个或两个以上运算符的表达式称为复合表达式.例如:3 + 2 * 5 如果 3 和 2 结合在 ...
- 易语言 大数计算 大数支持库的使用实例
部分数据过大需要使用到大数计算,网上暂时没看到简单的例子实例,所以记录下.希望能帮上需要的人. 以下代码直接复制到易语言即可使用.支持库里需要勾选上 数值计算支持库 EC模块下载地址:易语言大数 ...
- 单片机c语言除法运算,针对小容量单片机程序优化方式--乘除法篇
原标题:针对小容量单片机程序优化方式--乘除法篇 目前单片机的市场竞争很激烈,许多应用出于性价比的考虑,选择使用程序存储空间较小(如1K,2K)的小资源8位MCU芯片进行开发.一般情况下,这类MCU没 ...
- C语言实现大数运算(长整数的加、减、乘、除)
由于整型数的位数有限,因此整型数不能满足大整数(超长整数)的运算要求 .大整数计算是利用字符串来表示大整数,即用字符串的一位字符表示大整数的一位数值,然后根据四则运算规则实现大整数的四则运算. 简单表 ...
- C语言学习趣事_之_大数运算_加法
C语言学习趣事_大数运算_之加法 1.引子 在C语言中,因为预定义的自然数类型的大小是有上下限度的,这就决定了在进行数的运算的时候,必然受到限制,同时因为C语言是最接近汇编的一种程序设计语言,并 ...
- RSA与大数运算(C语言)
========================================================================== 前言:此文来自于www.pediy.com一位Cr ...
- SM2椭圆曲线公钥密码算法的C语言实现(基于Miracl大数运算库)
SM2椭圆曲线公钥密码算法的C语言实现(基于Miracl大数运算库) 实验环境 预备知识 FpF_pFp 及椭圆曲线 素域 FpF_pFp FpF_pFp 上的椭圆曲线 FpF_pFp 上椭圆 ...
- 怎么用c语言进行大数运算
在C语言中进行大数运算,一般有以下几种方式: 自己实现高精度计算库:通过定义自己的数据结构(比如用数组表示大整数)和实现基本的大数加减乘除等运算,可以实现高精度计算.但是这需要自己实现大量的代码,而且 ...
- Java的学习与java大数运算
之前就学过一点java,但太久没用知识点早就还给书本,之前在实验室搞到一本java的书,今天来重新温习一下 java的语法大部分和c++语言是一样的,入门非常快,所以在这里基础语句的用法就省略了 输出 ...
最新文章
- ICRA 2021| SKD:基于显着性估计的点云关键点检测
- SQL Server 自动增长清零
- 《JavaScript高级程序设计》阅读笔记(二十一):JavaScript中的XML
- 美国数学三大分支专业就业前景解析 你选对了吗?
- 程序员养生之道——坚持泡脚(十五分钟以上)
- python 硬件模拟_如何编写一个硬件模拟器?
- 【金融】【pytorch】使用深度学习预测期货收盘价涨跌——全连接神经网络模型构建与训练
- C++函数申明对函数模板实例化的屏蔽
- 分类问题:如何解决样本分布不均衡
- qt打开xls文件_Qt中打开excel文件
- 阿里飞猪一员工贩卖机票报销发票获利超千万被判六年
- 初识vue——vue的发展历程
- 全新电影社交观影,满足影迷移动巨幕与移动3D体验
- python京东图书信息抓取
- 【如何学习CAN总线测试】——Python+Robot Framework框架实现UDS诊断自动化
- 职位名称PM、RD、QA、OP英文缩写
- Android studio 启动模拟器出现 VT-x is disabled in BIOS 以及 /dev/kvm is not found
- camel_使用Apache Camel进行负载平衡
- 首尔半导体WICOP双色LED被用于2020款奥迪A4前灯
- 如何实现IEEE1588 高精度时间同步
热门文章
- mac完全卸载tuxera
- splite()方法的使用
- 计算机 拔电源 重启,电脑在关机就自动重新启动。但拔掉电源插头再关就又不会重新启动了。求高手帮忙!!!...
- 数据科学库(HM)_第2节_matplotlib绘图
- uni-app HBuilderX 工程转换 vue-cli 工程
- Matlab 2015b 启动时崩溃 MATLAB crashes during startup on Ubuntu 16.04
- 对View的onMeasure方法理解
- web3再牛 也没能逃出这几个老巨头的手掌心
- MySQL之——Linux单机启动多个MySQL实例(mysqld_multi )
- 练习print函数的使用(python)