C语言实现的高精度计算器
来源:互联网 发布:软件工程硕士 课程 编辑:程序博客网 时间:2024/05/27 00:43
原理:
使用数组存储数据,用模拟手工计算的方法实现。
代码:
/**************************************************************** RigorCalc.h: .*****************************************************************/#ifndef AFX_RIGORCALC_H__FC9C727A_5204_4798_9686_0CC00C25729C__INCLUDED_#define AFX_RIGORCALC_H__FC9C727A_5204_4798_9686_0CC00C25729C__INCLUDED_#define INT_BIT_MAX 255#define FLOAT_BIT_MAX 255#ifndef CONST #ifdef __cplusplus #define CONST const #else #define CONST #endif#endiftypedef struct tagWTNumber { int intbits; /* 整数数位*/ int floatbits; /* 小数有效数位*/ char infinite; /* 无穷大*/ char sign; /* 符号*/ char intpart[INT_BIT_MAX]; /* 整数部分*/ char floatpart[FLOAT_BIT_MAX]; /* 小数部分*/} WTNumber;/* 算术函数指针类型.*/typedef void (*PFNCALC)(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);/* 初始化WTNumber为0.*/void InitWTNumberToZero(WTNumber *pNum);/* 判断需要多少个字符空间存储WTNumber转换的字符串.*/int CharArrLenByWTNumber(CONST WTNumber* pNum);/* 从字符串转换到WTNumber.*/void CharArrToWTNumber(CONST char *arr,WTNumber *pNum);/* 从WTNumber转换到字符串.*/void WTNumberToCharArr(char *szBuf,CONST WTNumber *pNum);/* 调节数位,删除最高整数位是0的和最低小数位是0的数位.*/void AdjustBits(WTNumber *pNum);/* 移动小数点,deta=0不移动,deta<0往左移动,deta>0往右移动.*/void MoveFloatPoint(WTNumber *pNum,int deta);/* 使无穷大 */void MakeInfinite(WTNumber *pNum);/* 根据算术函数返回结果 */char *Result(CONST char *val1,CONST char *val2,PFNCALC pfnCalc);/* 比较2个数大小 */int WTCompare(CONST WTNumber* pn1,CONST WTNumber* pn2);/* 判断是否为0 */int IsZero(CONST WTNumber *pNum);/* 加法*/void WTAdd(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);/* 乘法*/void WTMultiply(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);/* 减法*/void WTSubtract(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);/* 除法*/void WTDivide(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);#endif /* AFX_RIGORCALC_H__FC9C727A_5204_4798_9686_0CC00C25729C__INCLUDED_ */
/************************************************* RigorCalc.c: implementation************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "Rigor.h"void InitWTNumberToZero(WTNumber *pNum){ memset(pNum,0,sizeof(WTNumber));}void AdjustBits(WTNumber *pNum){ while(pNum->intbits>1&&pNum->intpart[pNum->intbits-1]==0) pNum->intbits--; while(pNum->floatbits&&pNum->floatpart[pNum->floatbits-1]==0) pNum->floatbits--;}void MoveFloatPoint(WTNumber *pNum,int deta){ /* deta<0则往左移动小数点,deta>0则向右移动小数点 */ if(deta) { WTNumber n=*pNum; InitWTNumberToZero(pNum); pNum->sign=n.sign; if(deta<0) { int i; deta=-deta; for(i=deta;i<n.intbits;i++) { pNum->intpart[pNum->intbits++]=n.intpart[i]; } for(i=deta-1;i>=0;i--) { pNum->floatpart[pNum->floatbits++]=n.intpart[i]; } for(i=0;i<n.floatbits;i++) { pNum->floatpart[pNum->floatbits++]=n.floatpart[i]; } } else { int i; for(i=deta;i<n.floatbits;i++) /* 处理小数部分*/ { pNum->floatpart[pNum->floatbits++]=n.floatpart[i]; } for(i=deta-1;i>=0;i--) /* 小数到整数的部分*/ { pNum->intpart[pNum->intbits++]=n.floatpart[i]; } for(i=0;i<n.intbits;i++) /* 整数部分*/ { pNum->intpart[pNum->intbits++]=n.intpart[i]; } } } AdjustBits(pNum);}int CharArrLenByWTNumber(CONST WTNumber* pNum){ int len = pNum->floatbits+pNum->intbits+1; if(pNum->intbits==0) len++; /* .1 --> 0.1*/ if(pNum->floatbits) len++; /* '.'*/ if(pNum->sign) len++; /* '-'*/ if(pNum->infinite) return 11; /* #INFINITE */ return len;}void CharArrToWTNumber(CONST char *arr,WTNumber *pNum){ char *point; InitWTNumberToZero(pNum); if(*arr=='-') /* 如果是负数*/ { arr++; pNum->sign=1; } point=strchr(arr,'.'); if(point) /* 找到小数点 */ { int n=pNum->intbits=point-arr; /* 计算出整数数位 */ while(n) /* 整数数位不==0则循环 */ { pNum->intpart[pNum->intbits-n]=arr[n-1]-'0'; /* 将数字低位存在低下标元素*/ n--; } while(*++point) { pNum->floatpart[pNum->floatbits]=*point-'0'; pNum->floatbits++; } } else /* 说明没写小数点,全是整数.*/ { int n=pNum->intbits=strlen(arr); while(n) { pNum->intpart[pNum->intbits-n]=arr[n-1]-'0'; n--; } } AdjustBits(pNum); /* 处理-0 和0的情况*/ if(pNum->floatbits==0) { if(pNum->intbits==0 || pNum->intbits==1&&pNum->intpart[0]==0) pNum->sign=0; }}void WTNumberToCharArr(char *szBuf,CONST WTNumber* pNum){ int n=pNum->intbits,c; memset(szBuf,0,CharArrLenByWTNumber(pNum)); if(pNum->sign) /* 如果是负数*/ { *szBuf++='-'; } if(pNum->infinite) { strcat(szBuf,"#INFINITE"); return; } while(n) { szBuf[pNum->intbits-n]=pNum->intpart[n-1]+'0'; n--; } c=0; /* 是否加了0*/ if(pNum->intbits==0) { strcat(szBuf,"0"); c=1; } if(pNum->floatbits) strcat(szBuf,"."); n=0; while(n<pNum->floatbits) { szBuf[pNum->intbits+1+n+c]=pNum->floatpart[n]+'0'; n++; }}char *Result(CONST char *val1,CONST char *val2,PFNCALC pfnCalc){ static char *s_szRes=NULL; WTNumber n1,n2,res; if(s_szRes) { /*delete [] s_szRes;*/ free(s_szRes); s_szRes=NULL; } CharArrToWTNumber(val1,&n1); CharArrToWTNumber(val2,&n2); pfnCalc(&n1,&n2,&res);/* s_szRes = new char[CharArrLenByWTNumber(&res)];*/ s_szRes=(char*)malloc(CharArrLenByWTNumber(&res)*sizeof(char)); WTNumberToCharArr(s_szRes,&res); return s_szRes;}int WTCompare(CONST WTNumber* pn1,CONST WTNumber* pn2){ /* 首先是比较符号*/ if(pn1->sign==0&&pn2->sign!=0) /* pn1是正数,pn2是负数*/ return 1; /* >*/ else if(pn1->sign!=0&&pn2->sign==0) /* pn1是负数,pn2是正数*/ return -1; /* <*/ else /* 同号状态*/ { /* 比较整数部分*/ if(pn1->intbits>pn2->intbits) /* pn1整数数位多*/ return pn1->sign?-1:1; else if(pn1->intbits<pn2->intbits) return pn1->sign?1:-1; else /* 整数数位相同*/ { int i=pn1->intbits-1; /*指到最高位*/ while(i>=0) { if(pn1->intpart[i]>pn2->intpart[i]) return pn1->sign?-1:1; else if(pn1->intpart[i]<pn2->intpart[i]) return pn1->sign?1:-1; else i--; } /* 整数部分相同,比较小数部分*/ for(i=0;i<pn1->floatbits&&i<pn2->floatbits;) { if(pn1->floatpart[i]>pn2->floatpart[i]) return pn1->sign?-1:1; else if(pn1->floatpart[i]<pn2->floatpart[i]) return pn1->sign?1:-1; else i++; } if(i<pn1->floatbits) return pn1->sign?-1:1; if(i<pn2->floatbits) return pn1->sign?1:-1; return 0; /* 相等*/ } }}void MakeInfinite(WTNumber *pNum){ pNum->infinite=1;}int IsZero(CONST WTNumber* pNum){ if(pNum->floatbits==0&&pNum->intbits==0) return 1; if(pNum->floatbits==0&&pNum->intbits==1&&pNum->intpart[0]==0) return 1; return 0;}void WTAdd(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes){ InitWTNumberToZero(pRes); if(pn1->sign^pn2->sign) /*异号*/ { WTNumber n2=*pn2; n2.sign=pn1->sign; WTSubtract(pn1,&n2,pRes); } else /*同号*/ { int maxfloatbits=pn1->floatbits>pn2->floatbits?pn1->floatbits:pn2->floatbits; int addbit=0; /* 进位值*/ int i,j; for(i=maxfloatbits-1;i>=0;i--) { int value=pn1->floatpart[i]+pn2->floatpart[i]+addbit; addbit=value/10; /* 看看是否超过10. 设置进位值*/ pRes->floatpart[i]=value%10; } pRes->floatbits=maxfloatbits; /* 到此,小数部分计算完毕.*/ for(j=0;j<pn1->intbits||j<pn2->intbits;j++) { int value=pn1->intpart[j]+pn2->intpart[j]+addbit; addbit=value/10; pRes->intpart[j]=value%10; pRes->intbits++; } if(addbit>0) { pRes->intpart[j]=addbit; pRes->intbits++; } pRes->sign=pn1->sign; /*决定符号*/ AdjustBits(pRes); }}void WTMultiply(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes){ WTNumber z1=*pn1,z2=*pn2; WTNumber sum={0}; int i,j; InitWTNumberToZero(pRes); MoveFloatPoint(&z1,z1.floatbits); MoveFloatPoint(&z2,z2.floatbits); /* 计算z1*z2 */ for(i=0;i<z2.intbits;i++) { WTNumber tmp={0}; /* 存放临时乘积*/ int addbit=0; tmp.intbits=z1.intbits+i; for(j=0;j<z1.intbits;j++) { int value = z2.intpart[i]*z1.intpart[j]+addbit; addbit=value/10; tmp.intpart[j+i]=value%10; } if(addbit) { tmp.intpart[j+i]=addbit; tmp.intbits++; } WTAdd(&sum,&tmp,pRes); sum=*pRes; } *pRes=sum; MoveFloatPoint(pRes,-(pn1->floatbits+pn2->floatbits)); /* 判断符号,异号为负*/ if(pn1->sign^pn2->sign) pRes->sign=1;}void WTSubtract(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes){ InitWTNumberToZero(pRes); if(pn1->sign^pn2->sign) /* 异号情况*/ { WTNumber n2=*pn2; n2.sign=pn1->sign; WTAdd(pn1,&n2,pRes); } else /* 同号情况*/ { int cmp=WTCompare(pn1,pn2); int swapflag,i,maxfloatbits,subtractbit; if(cmp==0) return; /* 相等就没必要再减了.*/ swapflag=pn1->sign==0?cmp==-1:cmp==1; if(swapflag) { CONST WTNumber* p=pn1; pn1=pn2; pn2=p; } maxfloatbits=pn1->floatbits>pn2->floatbits?pn1->floatbits:pn2->floatbits; subtractbit=0; /* 退位值*/ /* 先计算小数部分*/ for(i=maxfloatbits-1;i>=0;i--) { if(pn1->floatpart[i]-subtractbit<pn2->floatpart[i]) { int value=pn1->floatpart[i]-pn2->floatpart[i]-subtractbit+10; subtractbit=1; pRes->floatpart[i]=value; } else { int value=pn1->floatpart[i]-pn2->floatpart[i]-subtractbit; subtractbit=0; pRes->floatpart[i]=value; } } pRes->floatbits=maxfloatbits; /* 至此小数部分计算完毕.*/ for(i=0;i<pn1->intbits||i<pn2->intbits;i++) { if(pn1->intpart[i]-subtractbit<pn2->intpart[i]) { int value=pn1->intpart[i]-pn2->intpart[i]-subtractbit+10; subtractbit=1; pRes->intpart[i]=value; } else { int value=pn1->intpart[i]-pn2->intpart[i]-subtractbit; subtractbit=0; pRes->intpart[i]=value; } pRes->intbits++; } pRes->sign=swapflag?!pn1->sign:pn1->sign; /*决定符号*/ AdjustBits(pRes); }}void WTDivide(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes){ WTNumber z1=*pn1,z2=*pn2; int deta=z2.floatbits-z1.floatbits; MoveFloatPoint(&z1,z1.floatbits); MoveFloatPoint(&z2,z2.floatbits); InitWTNumberToZero(pRes); if(IsZero(pn1)) return ; if(IsZero(pn2)) { pRes->sign=pn1->sign; MakeInfinite(pRes); return ; } z1.sign=z2.sign=0; /*统一符号,便于比较大小*/ while(z1.intbits!=z2.intbits) { /*确保数位相等,这步耗费很多时间*/ if(z1.intbits<z2.intbits) { MoveFloatPoint(&z1,1); deta--; } else { MoveFloatPoint(&z2,1); deta++; } } while(pRes->floatbits<(INT_BIT_MAX/2)) { int cmp=WTCompare(&z1,&z2); int n=10; WTNumber mulres={0},subres={0}; if(cmp==-1) { /*z1<z2*/ MoveFloatPoint(&z1,1); pRes->floatpart[pRes->floatbits++]=0; continue; } else if(cmp==0) { /*z1==z2*/ pRes->floatpart[pRes->floatbits++]=1; break; } do { /*找商*/ WTNumber tmp={0}; tmp.intpart[0]=--n; tmp.intbits=1; WTMultiply(&z2,&tmp,&mulres); } while((cmp=WTCompare(&mulres,&z1))==1); pRes->floatpart[pRes->floatbits++]=n; if(cmp==0) break; WTSubtract(&z1,&mulres,&subres); MoveFloatPoint(&subres,1); z1=subres; } MoveFloatPoint(pRes,1); MoveFloatPoint(pRes,deta); /* 判断符号,异号为负*/ if(pn1->sign^pn2->sign) pRes->sign=1;}
#include <stdio.h>#include "Rigor.h"typedef char CHARARR[256];int main(){ CHARARR num1; CHARARR num2; puts("Input two numbers,please:"); while(scanf("%s%s",num1,num2)!=-1) { printf("The result of addition:\n%s\n",Result(num1,num2,WTAdd)); printf("The result of subtration:\n%s\n",Result(num1,num2,WTSubtract)); printf("The result of multiplication:\n%s\n",Result(num1,num2,WTMultiply)); printf("The result of divide:\n%s\n",Result(num1,num2,WTDivide)); puts("Input two numbers,please:"); } return 0;}
声明:本文所引用代码系网络搜索所得,原作者未知,侵删。
0 0
- C语言实现的高精度计算器
- C语言实现的高精度加法
- 高精度加法的c语言实现
- c语言实现计算器
- C语言实现计算器
- C语言实现一个简单的计算器
- 一个计算器的C语言实现
- 用C语言实现的计算器
- C语言实现大数计算器
- C语言实现的简单的逆波兰计算器
- 栈实现的表达式计算器(c语言)
- 用C语言实现一个简单的计算器代码
- 求解高精度幂c语言实现
- 关于C语言实现高精度乘法运算
- C语言利用栈实现Polish计算器
- C语言实现基本计算器功能
- c语言计算器(栈实现)
- 逆波兰 计算器 C语言实现代码
- [深度好文]电动车真的很环保吗?
- 《Android源码设计模式》读书笔记 (10) 第10章 解释器模式
- CLH自旋锁
- 【ahk】获取网站的源代码
- 函数参数传递2
- C语言实现的高精度计算器
- “瀑布流式”图片懒加载代码解析及优化(二)
- 【C++】For、While、do···while循环
- Genymotion+VirtualBox详解—目录结构,路径更改,重新加载已存在的模拟器
- 2016蓝桥杯算法提高——身份证号码升级
- juce教程004-模态对话框
- Machine Learning - Regularized Linear Regression
- 278. First Bad Version
- 简单的网页版计算器