基于上一贴,修改减法运算适合于高精度浮点型计算。
因为减法比加法难度大一点,考虑的地方也要多一些,可能代码有欠缺,欢迎指出。
运算说明:
1、相减函数依旧没改变,包括上一贴的判断被减数与减数的大小函数也没变。
2、增加两个函数,取小数位数函数和结果处理(回归小数点)函数
3、与加法浮点高精度运算相比,这里改变较多的是结果处理函数,加法加完后,位数不减反增,而且最多增一位。减法会消失掉好多位,对于浮点型,即小数点后面的数,又得把零补回来,故函数增加了几个判断,具体看代码的注释说明。
程序测试效果如下:
以下代码包含四个函数功能,皆有注释:
#include "stdio.h" #include "string.h" /************************************************************************/ /* 高精度减法 (这个函数要a[]>=b[]) */ /* a[]被减数数组,位数不限 */ /* b[]减数数组,位数不限 */ /* back[]结果数组,位数不会大于a[]数组的 */ /************************************************************************/ void sub(char a[],char b[],char back[]) { int i,k,l1,l2; l1=strlen(a); l2=strlen(b); back[l1]='/0'; for (i=l2-1,l1--;i>=0;l1--,i--) //减数的个数小于等于被减数,所以减的次数依减数而定 { if (a[l1]-b[i]>=0) //不需要借位相减 { back[l1]=a[l1]-b[i]+'0'; } else //向前一位借1 { back[l1]=10+a[l1]-b[i]+'0'; if (a[l1-1]!='0') //当前一位非0,可以被借时,直接借来 { a[l1-1]-=1; } else //若前一位为0,则无法借到,继续向前一位的前一位借,循环 { k=l1-1; while (a[k]=='0') { a[k]='9'; //前一位的0,就变成了10,扣去被后一位借去的,还有9 k--; } a[k]-=1; //到达可以借的位置 } } } while (l1>=0) //被减数多于减数的位数直接赋给结果数组 { back[l1]=a[l1]; l1--; } while (back[0]=='0') //将结果数组往前移,方便以后的操作 { l1=strlen(a); for (i=0;i<l1-1;i++) { back[i]=back[i+1]; } back[l1-1]='/0'; } if (strlen(back)==0) //被减数与减数刚好相减为0的情况 { back[0]='0'; back[1]='/0'; } } /************************************************************************/ /* 判断函数(被减数与减数的大小比较) */ /* 可以用strcmp函数比较字符串 */ /* 比较完后,若小于减数,则置换带入高精度减法函数,最后加'-'输出 */ /************************************************************************/ bool isBigger(char a[],char b[]) { int l1,l2; l1=strlen(a); l2=strlen(b); if (l1>l2) { return true; } else if (l1<l2) { return false; } else { if (strcmp(a,b)>=0) { return true; } else { return false; } } } /************************************************************************/ /* 函数功能:返回小数点后的个数,并修改a,b数组为正整型 */ /* 先找出小数点的位置,比较小数点后的个数,返回比较大的个数,不足的那个补0 */ /************************************************************************/ int decimal(char a[],char b[]) { int i,j,k,l1,l2; l1=strlen(a); l2=strlen(b); for (i=0;i<l1;i++) { if (a[i]=='.') //找到小数点位置,然后删除小数点 { for (k=i;k<l1;k++) { a[k]=a[k+1]; } l1--; //长度减少 break; } } for (j=0;j<l2;j++) { if (b[j]=='.') { for (k=j;k<l2;k++) { b[k]=b[k+1]; } l2--; break; } } k=(l1-i)-(l2-j); //比较两个数组谁的小数位更多 if (i==l1 && j==l2) //都没有小数点的话,返回0 { return 0; } else if (k>=0) //被减数更多,b[]数组后面对齐补0 { while (k!=0) { b[l2++]='0'; k--; } return l1-i; //返回a[]的小数位数 } else if (k<0) //减数更多,a[]数组后面对齐补0 { k=k*-1; //记住k要变为正的 while (k!=0) { a[l1++]='0'; k--; } return l2-j; } } /************************************************************************/ /* 处理结果数组 */ /* 将数组小数点后面的后移,插入小数点 */ /* 处理小数点某位0的情况,要去掉,若是小数点后不含任何数,小数点也要去掉 */ /************************************************************************/ void result(char c[],int n) { int i,j,k,length; length=strlen(c); if (length==1 && c[0]=='0') //结果为0的话,不再处理,直接退出 { return ; } if (length<n) //结果的长度小于小数位数,则前面不止要补小数点还得补0 { j=n+2; for (i=length-1;i>=0;i--) { c[--j]=c[i]; } c[0]='0'; c[1]='.'; for (i=2;i<j;i++) { c[i]='0'; } } else //结果长度大于等于小数点,插入小数点即可(等于时再补个0) { for (i=length;i>length-n;i--) //数组后移length-n大小 { c[i]=c[i-1]; } c[length-n]='.'; //插入小数点 for (i=length;i>=length-n;i--) { if (c[i]!='0' && i!=length-n) //当不在小数点上面的时候,不为0直接退出 { break; } else //将0置为结束符,包括特定情况时去掉小数点 { c[i]='/0'; } } length=strlen(c); if (c[0]=='.') //小数点在第一位的话要后移,左补0 { for (i=length;i>0;i--) { c[i]=c[i-1]; } c[0]='0'; } } } /************************************************************************/ /* 主函数调用 */ /************************************************************************/ int main() { int n,k; char a[1000],b[1000],c[1000]; printf("%s","计算次数: "); scanf("%d",&n); while (n--) { memset(a,'/0',sizeof(a)); memset(b,'/0',sizeof(b)); memset(c,'/0',sizeof(c)); printf("%s","被减数: "); scanf("%s",&a); printf("%s","减数: "); scanf("%s",&b); k=decimal(a,b); //处理小数点 if (isBigger(a,b)) //处理被减数与减数的大小 { sub(a,b,c); //相减操作 if (k!=0) { result(c,k); //当是浮点数的话,对结果数组进行处理 } printf("%s%s/n/n","结果为: ",c); } else { sub(b,a,c); if (k!=0) { result(c,k); } printf("%s%c%s/n/n","结果为: ",'-',c); } } return 0; }