C语言-大整数四则运算
2016-04-17 21:06
411 查看
int的存储空间有限,利用”串”的结构,分享一则“大整数”简单四则运算。
资源下载位置:
http://pan.baidu.com/s/1sl1icmp
http://download.csdn.net/download/u013553804/9493994
欢迎关注我的微信个人订阅号
每天多学一点0.0
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct bigint { char *num; //指向长整数数组(序号0中保存着最高位) char minus; //符号(1表示正数,-1表示负数) int digit; //保存该数的位数(实际位数) }BIGINT, *pBIGINT; void BigIntTrans(pBIGINT num1) //将字符串转为数字表示 { char *temp; //临时数组 int i,k,len; len=strlen(num1->num); //字符串长度 //分配内存 if(!(temp = (char *)malloc(sizeof(char)* len))) { printf("内存分配失败!\n"); exit(0); } i=0; num1->minus=1; //保存为正数 if(num1->num[0]=='-') //判断是否为负数 { num1->minus=-1; i++; } k=0; //数字位数计数器 while(num1->num[i]!='\0') //字符串未结束 { if(num1->num[i]>='0' && num1->num[i] <='9') //数字为0~9 //将ASCII码转换为对应数字 temp[k]=num1->num[i]-'0'; k++; } i++; } for(i=0;i<num1->digit;i++) //清空数组各元素 num1->num[i]=0; num1->digit=k; //转换后的数据位数 for(i=0,k--;k>=0;k--,i++) //将临时数组各位置反置保存到数组num中 num1->num[i]=temp[k]; BigIntTrim(num1); //整理输入的大整数 } void BigIntTrim(pBIGINT num1) //整理大整数,去掉前面多余的0 { int i; for(i=num1->digit-1;i>=0;i--) //从高位检查是否为0 { if(num1->num[i] !=0) //遇到不为0的最高位 break; //跳出循环 } if(i<0) //若余数全部为0 { num1->digit=1; //设置余数位数为1 num1->num[0]=0; }else num1->digit=i+1; //余数位数 } void BigIntPrint(pBIGINT result) //输出大整数 { int j; if(result->minus ==-1) //是负数 printf("-"); //输出负数 //若大整数为0 if(result->digit ==1 &&result->num[0]==0) printf("0"); else //不为0 { //从高位到低位输出 for(j=result->digit-1;j>=0;j--) printf("%d",result->num[j]); } } int BigIntEqual(pBIGINT num1,pBIGINT num2) //比较绝对值大小 { int i; //num1的位数大于num2 if(num1->digit>num2->digit) return 1; //num1的位数小于num2 else if(num1->digit<num2->digit) return -1; else //两数位数相等 { i=num1->digit-1; //num1的数据位数 while(i>=0) //从高位向地位比 { //num1对应位大于num2 if(num1->num[i]>num2->num[i]) return 1; //num1对应位小于num2 else if(num1->num[i]<num2->num[i]) return -1; else //比较下一位 i--; } } return 0; //相等 } void BigIntAdd(pBIGINT num1,pBIGINT num2,pBIGINT result) { int i; i=BigIntEqual(num1,num2); //比较两数绝对值大小 if(i<0) //num1绝对值小于num2 { pBIGINT temp; temp=num1; //交换两数 num1=num2; num2=temp; } if(num1->minus * num2->minus <0) //符号不同,则执减法 { if(i==0) //两数相等 { //结果长度为一位数,就是数值0 result->digit =1; result->num[0]=0; //结果值为0 result->minus =1; //结果设为正号 return; //返回 } //调用相减函数完成异号相加 BigIntSub1(num1,num2,result); }else //调用相加函数完成同号相加 BigIntAdd1(num1,num2,result); } void BigIntAdd1(pBIGINT num1,pBIGINT num2,pBIGINT result) { int i,carry; carry=0; //清除进位 result->minus =num1->minus; //保存符号 //将被加数复制到结果数组中 for(i=0;i<num1->digit;i++) result->num[i]=num1->num[i]; //num2中的数小,可能位数也少些 for(i=0;i<num2->digit;i++) { //将对应位的数和进位数相加 result->num[i]=result->num[i]+num2->num[i]+carry; carry=result->num[i]/10; //计算进位数据 result->num[i]=result->num[i]%10; //保留一位 } if(carry) //若最后还有进位 result->num[i]=result->num[i]+carry; BigIntTrim(result); //整理结果 } //减法函数 void BigIntSub(pBIGINT num1,pBIGINT num2,pBIGINT result) { num2->minus =-1 * num2 ->minus; //将减数的符号取反 BigIntAdd(num1,num2,result); //调用加法函数 } //异号相减函数 void BigIntSub1(pBIGINT num1,pBIGINT num2,pBIGINT result) { int i,borrow; result->minus =num1->minus; //结果符号 borrow=0; //将被减数的内容复制到结果中 for(i=0;i<num1->digit;i++) result->num[i]=num1->num[i]; for(i=0;i<=num2->digit;i++) { //num1减去num2,并减去低位的借位 result->num[i]=result->num[i]-num2->num[i]-borrow; if(result ->num[i]<0) //若为负数 { result->num[i]=10+result->num[i]; //向高位借位 borrow=1; //设置借位数 }else borrow=0; } if(borrow==1) result->num[i]=result->num[i]-borrow; i=num1->digit; while(i>0) { if(result->num[i]==0) i--; else break; } result->digit=i+1; //保存结果位数 BigIntTrim(result); //整理结果 } void BigIntMul(pBIGINT num1,pBIGINT num2,pBIGINT result) { char carry,temp; int i,j,pos; //结果数组和中间数清0 for(i=0;i<num1->digit+num2->digit;i++) result->num[i]=0; //用乘数的每一位乘以被乘数 for(i=0;i<num2->digit;i++) { carry=0; //清除进位 //被乘数的每一位 for(j=0;j<num1->digit;j++) { //相乘并加上进位 temp=num2->num[i] * num1->num[j]+carry; //计算进位carry carry =temp/10; //计算当前位的值 temp=temp%10; pos=i+j; //计算结果累加到临时数组中 result->num[pos]+=temp; carry=carry+result->num[pos]/10; //计算进位 result->num[pos]=result->num[pos]%10; } if(carry>0) { result->num[i+j]=carry; //加上最高位进位 result->digit=i+j+1; //保存结果位数 }else result->digit=i+j; //保存结果位数 } result->minus=num1->minus * num2->minus; //结果的符号 } void BigIntDiv(pBIGINT num1,pBIGINT num2,pBIGINT result,pBIGINT residue) //除法函数 { BIGINT quo1,residol,quo2; int i,j,k,m; //k保存试商结果,m保存商的位数 char t; result->minus = num1->minus * num2->minus; //商的符号 //分配余数的内存空间 residue->num =(char *)malloc(sizeof(char) * num2->digit); for(i=0;i<residue->digit;i++) //将余数全部清0 residue->num[i]=0; m=0; for(i=num1->digit-1;i>=0;i--) { //重新设置余数的位数比除数多一位 residue->digit=num2->digit+1; for(j=num2->digit-1;j>0;j--) //移余数 residue->num[j]=residue->num[j-1]; //复制被除数中的一位到余数的最低位中 residue->num[0]=num1->num[i]; BigIntTrim(residue); //整理余数 k=0; //试商 //比较余数与除数的大小 while(BigIntEqual(residue,num2)>=0) { BigIntSub1(residue,num2,residue); //用余数减去除数,差值保存在余数中 k++; //试商加1 } result->num[m++]=k; //保存商 } result->digit=m; //保存商的位数 for(i=0;i<m/2;i++) //反转商的值 { t=result->num[i]; result->num[i]=result->num[m-1-i]; result->num[m-1-i]=t; } BigIntTrim(result); //整理商 BigIntTrim(residue); //整理余数 } int main() { //参与运算的数,结果,余数 BIGINT num1,num2,result,residue; int i=0,len; char op; printf("输入最大数的位数:"); scanf("%d",&len); if(!(num1.num=(char *)malloc(sizeof(char) * (len+1))) ) { printf("内存分配失败!\n"); exit(0); } num1.digit=len +1; if(!(num2.num=(char *)malloc(sizeof(char) * (len +1)))) { printf("内存分配失败!\n"); exit(0); } num2.digit=len+1; if(!(result.num=(char *)malloc(sizeof(char) * (2*len +1)))) { printf("内存分配失败!\n"); exit(0); } result.digit=2*len+1; for(i=0;i<result.digit;i++) //清空结果集 result.num[i]=0; printf("选择大整数的运算(+,-,*,/):"); fflush(stdin); scanf("%c",&op); switch(op) { case '+': printf("\n输入被加数:"); scanf("%s",num1.num); printf("\n输入加数:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); BigIntAdd(&num1,&num2,&result); //加法 break; case '-': printf("\n输入被减数:"); scanf("%s",num1.num); printf("\n输入减数:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); BigIntSub(&num1,&num2,&result); //减法 break; case '*': printf("\n输入被乘数:"); scanf("%s",num1.num); printf("\n输入乘数:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); BigIntMul(&num1,&num2,&result); //乘法 break; case '/': printf("\n输入被除数:"); scanf("%s",num1.num); printf("\n输入除数:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); if(num2.digit==1 && num2.num[0]==0) //大整数为0 printf("除数不能为0!\n"); else BigIntDiv(&num1,&num2,&result,&residue); //除法 break; } if(op=='/') { //为除法且除数不为0 if(!(num2.digit==1 && num2.num[0]==0)) { printf("商:"); BigIntPrint(&result); printf("\t余数:"); BigIntPrint(&residue); } }else { printf("结果:"); BigIntPrint(&result); } getch(); return 0; }
资源下载位置:
http://pan.baidu.com/s/1sl1icmp
http://download.csdn.net/download/u013553804/9493994
欢迎关注我的微信个人订阅号
每天多学一点0.0
相关文章推荐
- C++: std::string 与 Unicode 如何结合?
- SM2算法第一篇:ECC加密算法
- C++动态规划
- 棋盘覆盖问题
- C++类型转换运算符之const_cast<newtype>(expression)
- C语言隐式数据类型转换
- VPTR和VTABLE和构造函数与继承
- c/c++中求取字符串,数组,一块内存的长度
- 关于循环重复数字的相加 C语言越来越好玩
- C++中的哑类
- 初探C++类模版学习笔记
- thrift C++做server, C++,python, java做Client例子
- 巩固C语言(八)----进程和线程的区别和练习 & 线程编程
- 学习OpenCV——Kmean(C++)
- 大型分布式C++框架《四:netio之请求包中转站 上》
- sizeof陷阱
- 程序编译链接运行深入剖析
- MFC发送邮件C语言版
- C++编译过程与内存空间
- [vs2010 project] CppUnit快速入门