数组实现高精度除法异常排查:部分用例无输出或结果错误
高精度除法模块异常问题分析
异常现象
- 输入
/ 100000000 999或/ 10000 99无输出 / 1000 99输出正确结果10/ 30 1得到错误输出29/ 1000000000 99计算出错,但/ 2300 200输出正确- 疑问:异常是超时导致还是其他原因?
相关代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LEN 1000 int an1[MAX_LEN+10], an2[MAX_LEN+10]; char szLine1[MAX_LEN+10], szLine2[MAX_LEN+10]; void mul(int a[], int an, int b[], int bn, int fa, int fb); void plus(int an1[], int an2[]); void div(int an1[], int nlen1, int an2[], int nlen2, int fa, int fb); void sub(int an1[], int nLen1, int an2[], int nLen2); int compare_num(int an1[], int nLen1, int an2[], int nLen2); int main(){ char op = getchar(); getchar(); int i = 0, j = 0, nLen1 = 0, nLen2 = 0; memset(an1, 0, sizeof(an1)); memset(an2, 0, sizeof(an2)); int fa = 1, fb = 1; scanf("%s", szLine1); nLen1 = strlen(szLine1); scanf("%s", szLine2); nLen2 = strlen(szLine2); if(szLine1[0] == '-') fa = -1; if(szLine2[0] == '-') fb = -1; if(fa == -1){ for(i = nLen1-1; i >= 1; i--){ an1[j++] = szLine1[i] - '0'; }}else{ for(i = nLen1-1; i >= 0; i--){ an1[j++] = szLine1[i] - '0'; }} if(fb == -1){ for(i = nLen1-1; i >= 1; i--){ an2[j++] = szLine2[i] - '0'; }}else{ for(i = nLen2-1, j = 0; i >= 0; i--){ an2[j++] = szLine2[i] - '0'; } } //以上两个循环将szline中的输入的数组倒置放入an数组中 switch (op) { case '+': plus(an1, an2); break; case '-': sub(an1, nLen1, an2, nLen2); break; case '*': mul(an1, nLen1, an2, nLen2, fa, fb); break; case '/': div(an1, nLen1, an2, nLen2, fa, fb); break; default: break; } return 0; } int compare_num(int an1[], int nLen1, int an2[], int nLen2){ int count = 0; if(nLen1 > nLen2) return 1; else if(nLen1 < nLen2) return -1; else if(nLen1 == nLen2){ for(int i = nLen1; i >= 0; i--){ if(an1[i] > an2[i]) return 1; else if(an1[i] < an2[i]) return -1; else if(an1[i] == an2[i]){ count++; continue; } } if(count == nLen1) return 0; } } void div(int an1[], int nlen1, int an2[], int nlen2, int fa, int fb){ int count = 0; int sign = compare_num(an1, nlen1, an2, nlen2); if(sign == 1){ while(compare_num(an1, nlen1, an2, nlen2) == 1 || compare_num(an1, nlen1, an2, nlen2) == 0){ for(int i = 0; i <= nlen2; i++){ if(an2[i] > an1[i]){ an1[i] = an1[i]+10-an2[i]; an1[i+1]--; }else{ an1[i] = an1[i] - an2[i];}} if(an1[nlen1-1] == 0) nlen1--; count++; if(nlen1 < nlen2) break; } if(fa * fb < 0) printf("-"); printf("%d", count); }else{ printf("0"); } }
问题根源分析
除数初始化错误:处理负数除数时,循环误用了被除数的长度
nLen1而非除数长度nLen2,导致an2数组值完全错误,后续比较、减法逻辑全部失效。代码错误片段:if(fb == -1){ for(i = nLen1-1; i >= 1; i--){ // 此处应使用nLen2 an2[j++] = szLine2[i] - '0'; }}减法逻辑缺陷:除法中的逐次减法仅处理当前位借位,未处理高位借位后的连锁反应。例如
/30 1时,第一次减完后an1变成29,后续循环无法正确终止,导致计数错误。暴力除法导致超时:当前除法采用逐次减去除数的暴力实现,当被除数远大于除数时(如
100000000 / 999),循环次数达百万级,程序长时间无响应,表现为“无输出”。compare_num函数未定义行为:函数存在路径未返回值的情况(如所有位相等但
count未达到nLen1时),可能导致比较结果混乱。
修复建议
- 修正除数初始化的循环变量,将
nLen1改为nLen2。 - 重写减法逻辑,正确处理连续借位:从低位到高位逐位相减,若当前位不够减则向高位借1,高位减1后当前位加10再减。
- 替换暴力除法为试商法,通过移位快速确定商的每一位,避免大量循环。
- 简化
compare_num函数,去掉冗余的count变量,确保所有分支都有明确返回值。
内容的提问来源于stack exchange,提问作者HHK
相关产品推荐
相关产品推荐

