C语言超长整数相乘代码结果错误,求问题排查
超长整数乘法代码问题排查与修复
问题背景
用C语言实现两个长度不超过200位的超长整数乘法,实际输出结果与预期不符,测试用例如下:
测试用例
- 输入:
first_num:2312730179961343894238242938502761288775
second_num:8783549656928600320634308588114585640082 - 预期输出:
20313980378767882242186765287491308230145683219100946334095285964698734616679550 - 实际输出:
110313971037876788224218676528749130822101456832190100946334095285964698734616679550
原代码
#include <stdio.h> #include <string.h> #include <math.h> #define MAX_LEN 200 int checkValidInputNum(char*); int main() { char first_num[MAX_LEN]; char second_num[MAX_LEN]; printf("Please Enter your first number:\n"); scanf("%s", first_num); checkValidInputNum(first_num); printf("Please Enter your second number:\n"); scanf("%s", second_num); checkValidInputNum(second_num); int output_num_len = strlen(first_num) +strlen(second_num); int shifting, inputDataRemainder, inputDataQuotient; int output_num[output_num_len]; for (int i = 0; i < output_num_len; i++) { output_num[i]=0; //Fill output string of output_num_len with zeroes //printf("%i", output[i]); } for(int i = 0 ; i <strlen(first_num) ; i++) { for (int j= 0 ; j < strlen(second_num); j++) { shifting = (strlen(first_num) -1 - i) +(strlen(second_num) -1 - j); inputDataRemainder = ((first_num[i]-48) * (second_num[j]-48)) % 10; inputDataQuotient = floor((first_num[i]-48) * (second_num[j]-48)/10); if (output_num[0+shifting] + inputDataRemainder > 9) { output_num[1+shifting] += floor((inputDataRemainder + output_num[0+shifting]) / 10); output_num[0+shifting] = (output_num[0+shifting] + inputDataRemainder)%10; //printf("Check1"); } else { output_num[0+shifting] += inputDataRemainder; //printf("Check2"); } if (output_num[1+shifting] + inputDataQuotient > 9) { output_num[2+shifting] += floor((inputDataQuotient + output_num[1+shifting]) / 10); output_num[1+shifting] = (output_num[1+shifting] + inputDataQuotient)%10; //printf("Check3"); } else { output_num[1+shifting] += inputDataQuotient; //printf("Check4"); } } } if (output_num[output_num_len-1] != 0) printf("%i", output_num[output_num_len - 1]); printf("The answer is:"); for (int i = output_num_len - 2; i > -1 ; i--) { printf("%i", output_num[i]); } printf("\n"); } int checkValidInputNum(char* text) { for(int i = 0 ; i <strlen(text) ; i++) { if (text[i] < 48 || text[i] > 57) { printf("Please Enter your input again:\n"); scanf("%s", text); return checkValidInputNum(text); } } return 0; }
问题分析
- 进位处理不彻底:原代码将乘积拆分为余数和商后,分别对两个位置做局部进位处理,无法应对连续进位场景(比如某一位相加后产生的进位导致下一位也超过10),会导致数值叠加错误。
- 乘积拆分处理逻辑冗余且易出错:刻意拆分余数和商分别加到数组的两个位置,不如直接将完整乘积加到对应位置后统一处理进位,逻辑更清晰且不易出错。
- 输出逻辑不严谨:仅单独处理最高位的前导零,未考虑中间可能存在的前导零情况,且输出顺序的处理容易导致数值顺序错误。
修复方案
- 调整乘积累加逻辑:不再拆分余数和商,直接将两个数字的乘积加到对应的数组位置(
shifting对应的索引)。 - 统一处理所有进位:遍历输出数组,从最低位到最高位,依次计算每一位的进位,将进位传递到下一位,当前位保留个位数值。
- 修正输出逻辑:找到第一个非零的最高位索引,从该索引开始依次输出到最低位,确保无多余前导零;若结果全为零,则输出0。
修复后的代码
#include <stdio.h> #include <string.h> #define MAX_LEN 200 int checkValidInputNum(char*); int main() { char first_num[MAX_LEN]; char second_num[MAX_LEN]; printf("Please Enter your first number:\n"); scanf("%s", first_num); checkValidInputNum(first_num); printf("Please Enter your second number:\n"); scanf("%s", second_num); checkValidInputNum(second_num); int len1 = strlen(first_num); int len2 = strlen(second_num); int output_num_len = len1 + len2; int output_num[output_num_len]; // 初始化输出数组为0 for (int i = 0; i < output_num_len; i++) { output_num[i] = 0; } // 累加所有乘积到对应位置 for (int i = 0; i < len1; i++) { int digit1 = first_num[i] - '0'; for (int j = 0; j < len2; j++) { int digit2 = second_num[j] - '0'; int shifting = (len1 - 1 - i) + (len2 - 1 - j); output_num[shifting] += digit1 * digit2; } } // 统一处理进位 for (int i = 0; i < output_num_len - 1; i++) { output_num[i + 1] += output_num[i] / 10; output_num[i] = output_num[i] % 10; } // 找到第一个非零的最高位 int start_idx = output_num_len - 1; while (start_idx > 0 && output_num[start_idx] == 0) { start_idx--; } // 输出结果 printf("The answer is:"); for (int i = start_idx; i >= 0; i--) { printf("%d", output_num[i]); } printf("\n"); return 0; } int checkValidInputNum(char* text) { int len = strlen(text); for (int i = 0; i < len; i++) { if (text[i] < '0' || text[i] > '9') { printf("Please Enter your input again:\n"); scanf("%s", text); return checkValidInputNum(text); } } return 0; }
内容的提问来源于stack exchange,提问作者Revanth Tv
相关产品推荐
相关产品推荐

