免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5341 | 回复: 4
打印 上一主题 下一主题

[算法] 高精度减法的问题! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-12-23 19:38 |只看该作者 |倒序浏览
3可用积分
下面是一个实现高精度减法的程序,a[],b[]存放两个操作数,r[]存放结果。
算法是用两个指针p,q操作数组的,其中p始终指向大的操作数组,q指向小的操作数组。
程序运行的结果有问题,请高手帮忙看看,程序哪些地方有问题?谢谢

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int main(int argc, char** argv)
  4. {
  5.         int                     a[100], b[100], r[100];//数组p保存结果
  6.         int                     i = 0, j = 0;
  7.         int                     len1, len2, val_p, val_q, k, c, m;
  8.         int                     *p = NULL, *q = NULL;//p指向大数数组,q指向小数数组


  9.         for(k = 0; k < 100; k++){
  10.                 a[k] = 0;
  11.                 b[k] = 0;
  12.                 r[k] = 0;
  13.         }

  14.         while((c = getchar()) != '\n'){
  15.                 a[i] = c - 48;
  16.                 i++;
  17.         }//输入一个减数,i是a的长度

  18.         while((c = getchar()) != '\n'){
  19.                 b[j] = c - 48;//字符转化为整数
  20.                 j++;
  21.         }//输入被减数,j是b的长度

  22.         i--;
  23.         j--;
  24.         m = (i > j) ? i : j;//m是i,j中的最大值
  25.         if(i > j){
  26.                 p = a;
  27.                 q = b;
  28.                 len1 = i;
  29.                 len2 = j;
  30.         }
  31.         else{
  32.                 p = b;
  33.                 q = a;
  34.                 len1 = j;
  35.                 len2 = i;
  36.         }//p始终指向长数组,len1始终表示P所表示数的长度

  37.         for(k = m; k > 0; k--){
  38.                 if((len1 >= 0) && (len2 >= 0)){
  39.                         val_p = *(p+len1);
  40.                         val_q = *(q+len2);
  41.                 }
  42.                 else if((len1 >= 0) && (len2 < 0)){
  43.                         val_p = *(p+i);
  44.                         val_q = 0;
  45.                 }

  46.                 if(val_p >= val_q){
  47.                         r[k] = val_p - val_q;
  48.                 }
  49.                 else{//借位
  50.                         (*(p+len1-1))--;
  51.                         r[k] = 10 + val_p - val_q;
  52.                 }
  53.                 len1--;
  54.                 len2--;
  55.         }

  56.         if((i <= j) && (a[0] < b[0])){//此条件满足,表示减数小于被减数,结果是负数
  57.                 printf("-");
  58.         }
  59.         if(r[0] != 0){
  60.                 printf("%d", r[0]);
  61.         }
  62.         for(k = 1; k <= m; k++){
  63.                 printf("%d", r[k]);
  64.         }
  65.         printf("\n");

  66.         exit(0);
  67. }
复制代码

最佳答案

论坛徽章:
0
2 [报告]
发表于 2007-12-23 19:38 |只看该作者
>>if((i <= j) && (a[0] < b[0])){//此条件满足,表示减数小于被减数,结果是负数

这个逻辑是错误的, a[0], b[0] 是最高位,为什么要用 && 呢?

而且当 i=j 时,a<b 并不意味着 a[0]<b[0],比如  11<12

如果用十进制,一般的处理是这样的,a, b 都看成是 n 个十进制位,其中 n 是 a,b 中长度较大者。

用一个 c 去记录借位,0 表示没有借位, -1 表示借了位

如果最后 c 是 0,则得到结果,如果 c 是负数,则表示 a<b, 计算的实际上是 10^n+a-b,所以再用 10^n 减去当前结果(10^n+a-b)得到 b-a, 结果为负的  b-a。

如果发现 c 最终小于 0 后,不想用 10^n 去减中间结果,则直接用 b 去减 a 也可以。

论坛徽章:
0
3 [报告]
发表于 2007-12-23 20:37 |只看该作者
<c语言接口与实现>  里面有介绍任意精度算法 ,你可以看看

论坛徽章:
0
4 [报告]
发表于 2007-12-23 21:17 |只看该作者
事实上在长度相等时,你可以逐位比较,弄清楚谁大再减,这样比较简洁。

论坛徽章:
0
5 [报告]
发表于 2007-12-24 00:18 |只看该作者

已经解决,能实现功能!代码质量很差,能否改进一下?


  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int main(int argc, char** argv)
  4. {
  5.         int                     a[100], b[100], r[100];//数组p保存结果
  6.         int                     i = 0, j = 0;
  7.         int                     len1, len2, val_p, val_q, k, c, ch, m;
  8.         int                     *p = a, *q = b;//p指向大数数组,q指向小数数组

  9.         for(k = 0; k < 100; k++){
  10.                 a[k] = 0;
  11.                 b[k] = 0;
  12.                 r[k] = 0;
  13.         }

  14.         while((ch = getchar()) != '\n'){
  15.                 a[i] = ch - 48;
  16.                 i++;
  17.         }//输入一个减数,i是a的长度

  18.         while((ch = getchar()) != '\n'){
  19.                 b[j] = ch - 48;//字符转化为整数
  20.                 j++;
  21.         }//输入被减数,j是b的长度

  22.         i--;
  23.         j--;
  24.         m = (i > j) ? i : j;//m是i,j中的最大值

  25. //判断谁是大的操作数,并用p指向它,len1表示它的长度
  26.         if(i > j){
  27.                 p = a;
  28.                 q = b;
  29.                 len1 = i;
  30.                 len2 = j;
  31.         }
  32.         else if(i < j){
  33.                 p = b;
  34.                 q = a;
  35.                 len1 = j;
  36.                 len2 = i;
  37.         }
  38.         else if(i == j){
  39.                 for(k = 0; k < i; k++){
  40.                         if(a[k] > b[k]){
  41.                                 p = a;
  42.                                 q = b;
  43.                                 len1 = i;
  44.                                 len2 = j;
  45.                                 break;
  46.                         }
  47.                         if(a[k] < b[k]){
  48.                                 p = b;
  49.                                 q = a;
  50.                                 len1 = j;
  51.                                 len2 = i;
  52.                                 break;
  53.                         }
  54.                 }//for
  55.         }

  56.         for(k = m; k >= 0; k--){
  57.                 if((len1 >= 0) && (len2 >= 0)){
  58.                         val_p = *(p+len1);
  59.                         val_q = *(q+len2);
  60. //                      printf("val_p = %d, val_q = %d\n", val_p, val_q);
  61.                 }
  62.                 else if((len1 >= 0) && (len2 < 0)){
  63.                         val_p = *(p+len1);
  64.                         val_q = 0;
  65.                 }

  66.                 if(val_p >= val_q){
  67.                         r[k] = val_p - val_q;
  68.                 }
  69.                 else{//借位
  70.                         (*(p+len1-1))--;
  71.                         r[k] = 10 + val_p - val_q;
  72.                 }
  73.                 len1--;
  74.                 len2--;
  75.         }

  76.         if(p == b){
  77.                 printf("-");
  78.         }

  79.         if(r[0] != 0){
  80.                 printf("%d", r[0]);
  81.         }

  82.         for(k = 1; k <= m; k++){
  83.                 printf("%d", r[k]);
  84.         }
  85.         printf("\n");

  86.         exit(0);
  87. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP