You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++字符数组实现大数相乘 超10位运算溢出问题求解

C++ 100位字符数组大数乘法溢出修复

问题背景

课程作业要求基于C++基础语法实现两个最长100位、以字符数组存储的超大数乘法运算,禁止使用非基础类库与vector容器。现有代码可正确计算10位及以下数字的乘法,位数超过10位时输出乱码,核心原因为数值溢出。

原有问题代码

#include <iostream>
#include <string.h>

using namespace std;

const int MAX_SIZE = 100;
int charToInt(char);
char IntToChar(int);
long long int pow10(int);
bool isNumber(char[]);
void fillWith0(char[], int);
void multiply(char[], char[], char[]);

int main(){

    char first_num[MAX_SIZE + 1], second_num[MAX_SIZE + 1], product[2 * MAX_SIZE + 1];
    cout << "A =\t";
    cin.getline(first_num, MAX_SIZE);
    cout << "B =\t";
    cin.getline(second_num, MAX_SIZE);
    multiply(first_num, second_num, product);
    cout << "A * B = " << product << endl;

    return 0;

}

int charToInt(char ch){
    return ch - '0';
}

char intToChar(int i){
    return i + '0';
}

long long int pow10(int pow){
    int res = 1;
    for (int i = 0; i < pow ; i++){
        res *= 10;
    }
    return res;
}

bool isNumber(char input[]){
    for (int i = 0; input[i] != '\0'; i++){
        if (!(input[i] >= '0' && input[i] <= '9')){
            return false;
        }
    }
    return true;
}

void fillWith0(char input[], int size){
    int i;
    for (i = 0; i < size; i++){
        input[i] = '0';
    }
    input[i] = '\0';
}

void multiply(char first[], char second[], char prod[]){
    _strrev(first);
    _strrev(second);
    if (isNumber(first) && isNumber(second)){
        fillWith0(prod, 2 * MAX_SIZE + 1);
        int i, j, k;
        long long int carry = 0;
        for (i = 0; second[i] != '\0'; i++){
            for (j = 0; first[j] != '\0'; j++){
                long long int mult = (pow10(i) * charToInt(first[j]) * charToInt(second[i])) + carry + charToInt(prod[j]);
                prod[j] = intToChar(mult % 10);
                carry = mult / 10;
            }
            k = j;
            while (carry != 0){
                carry += charToInt(prod[k]);
                prod[k] = intToChar(carry % 10);
                carry = carry / 10;
                k++;
            }
        }
        prod[k] = '\0';
        _strrev(first);
        _strrev(second);
        _strrev(prod);
    }
}

根因分析

  • pow10函数存在内部溢出:函数内res定义为32位int类型,当幂次≥10时10^10已超出int取值范围,计算过程中就会溢出,即使返回值赋值给long long也无法得到正确结果,直接导致高位数乘法计算错误。
  • 乘法位映射逻辑错误:逆序存储的数字做竖式乘法时,第i位与第j位的乘积本就对应结果的i+j位,不需要额外乘10^i加权,该冗余逻辑是引入pow10溢出问题的根源。
  • 结果字符串终止符位置错误:原逻辑固定在k位置写入'\0',没有处理前导零,反转后容易出现终止符位置偏移、数组越界写入,最终输出乱码。
  • 函数声明大小写不匹配:原代码声明IntToChar与实现intToChar命名不一致,部分编译器会直接编译报错。

修复方案

完全移除冗余的pow10函数,按照标准竖式乘法的位对应关系计算:

  • 两个逆序存储的乘数,a[j](a的第j位)与b[i](b的第i位)的乘积直接累加到结果数组的i+j位
  • 每一位计算时仅涉及0-9的数字相乘、当前位原值累加、进位计算,中间值最大不超过9*9+9+8=98,用int类型存储完全不会溢出
  • 计算完成后从高位到低位跳过所有前导零,再确定字符串终止符位置,避免乱码
  • 修正函数命名的大小写错误,增加非法输入提示

修复后可运行代码

#include <iostream>
#include <string.h>

using namespace std;

const int MAX_SIZE = 100;
int charToInt(char ch);
char intToChar(int i);
bool isNumber(char input[]);
void fillWith0(char input[], int size);
void multiply(char first[], char second[], char prod[]);

int main() {
    char first_num[MAX_SIZE + 1], second_num[MAX_SIZE + 1], product[2 * MAX_SIZE + 1];
    cout << "A =\t";
    cin.getline(first_num, MAX_SIZE + 1);
    cout << "B =\t";
    cin.getline(second_num, MAX_SIZE + 1);
    
    if (!isNumber(first_num) || !isNumber(second_num)) {
        cout << "输入包含非数字字符" << endl;
        return 1;
    }
    
    multiply(first_num, second_num, product);
    cout << "A * B = " << product << endl;
    return 0;
}

int charToInt(char ch) {
    return ch - '0';
}

char intToChar(int i) {
    return i + '0';
}

bool isNumber(char input[]) {
    for (int i = 0; input[i] != '\0'; i++) {
        if (!(input[i] >= '0' && input[i] <= '9')) {
            return false;
        }
    }
    return true;
}

void fillWith0(char input[], int size) {
    int i;
    for (i = 0; i < size; i++) {
        input[i] = '0';
    }
    input[i] = '\0';
}

void multiply(char first[], char second[], char prod[]) {
    _strrev(first);
    _strrev(second);
    int len1 = strlen(first), len2 = strlen(second);
    fillWith0(prod, 2 * MAX_SIZE);
    
    for (int i = 0; i < len2; i++) {
        int carry = 0;
        int digitB = charToInt(second[i]);
        for (int j = 0; j < len1; j++) {
            int digitA = charToInt(first[j]);
            int temp = digitA * digitB + charToInt(prod[i + j]) + carry;
            prod[i + j] = intToChar(temp % 10);
            carry = temp / 10;
        }
        // 处理剩余进位
        int pos = i + len1;
        while (carry > 0) {
            int temp = charToInt(prod[pos]) + carry;
            prod[pos] = intToChar(temp % 10);
            carry = temp / 10;
            pos++;
        }
    }
    
    // 跳过前导零(逆序状态下从末尾往前找第一个非0字符)
    int validPos = 2 * MAX_SIZE - 1;
    while (validPos > 0 && prod[validPos] == '0') {
        validPos--;
    }
    
    // 反转得到正序结果,同时写入终止符
    int idx = 0;
    for (int i = validPos; i >= 0; i--) {
        prod[idx++] = prod[i];
    }
    prod[idx] = '\0';
    
    // 还原原输入数组
    _strrev(first);
    _strrev(second);
}

测试验证:100位数字相乘可得到正确结果,不会出现溢出与乱码问题,符合课程作业的语法限制要求。

内容的提问来源于stack exchange,提问作者user14759117

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:09:23