C++基于字符串实现大数相乘问题的代码详解

 更新时间:2025年03月31日 11:21:23   作者:倔强的石头_  
在实际编程中,我们经常会遇到需要处理大整数的情况,由于编程语言中内置整数类型有其表示范围的限制,当需要处理的整数超出这些范围时,就不能直接使用内置类型进行计算,所以本文给大家介绍了相关的解决方法,需要的朋友可以参考下

一、问题描述

在实际编程中,我们经常会遇到需要处理大整数的情况。由于编程语言中内置整数类型(如 intlong 等)有其表示范围的限制,当需要处理的整数超出这些范围时,就不能直接使用内置类型进行计算。
一般的解决方式是以两个以字符串形式表示的非负整数 num1 和 num2 的乘法,并将结果也以字符串形式返回。

输入限制

  • 1 <= num1.length, num2.length <= 200
  • num1 和 num2 只能由数字组成。
  • num1 和 num2 都不包含任何前导零,除了数字 0 本身。

二、解题思路

要解决这个问题,我们可以模拟手工乘法的过程。在手工乘法中,我们将一个数的每一位与另一个数的每一位相乘,然后将结果相加,并处理进位。具体步骤如下:

  1. 特殊情况处理:如果 num1 或 num2 为 "0",则直接返回 "0"
  2. 反转字符串:为了方便从低位到高位进行计算,我们将 num1 和 num2 反转。
  3. 初始化结果数组:创建一个长度为 num1.size() + num2.size() 的数组 ret,用于存储中间结果。因为两个数相乘的结果位数不会超过这两个数的位数之和。
  4. 逐位相乘:使用两层循环,将 num1 的每一位与 num2 的每一位相乘,并将结果累加到 ret 数组的相应位置。
  5. 处理进位:遍历 ret 数组,将每一位的进位加到下一位。
  6. 去除前导零:由于结果数组可能存在前导零,我们需要将其去除。
  7. 转换为字符串:将处理好的结果数组转换为字符串。

三、代码实现

#include <string>
#include <algorithm>

class Solution {
public:
    string multiply(string num1, string num2) 
    {
        // 先判断是否有一个为0
        if(num1 == "0" || num2 == "0")
            return "0";

        // 反转两个字符串方便操作
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());

        // 结果位数不超过两个字符串之和
        int size = num1.size() + num2.size();

        // 创建存储结果的数组并初始化为0
        int* ret = new int[size]();
        
        // 字符串相乘,不考虑进位
        for(int i = 0; i < num1.size(); ++i)
        {
            for(int j = 0; j < num2.size(); ++j)
            {
                ret[i + j] += (num1[i] - '0') * (num2[j] - '0');
            }
        }

        // 处理进位
        for(int i = 0; i < size - 1; ++i)
        {
            ret[i + 1] += ret[i] / 10;
            ret[i] = ret[i] % 10;
        }
        
        // 去除前导零
        int i = size - 1;
        while( (ret[i] == 0) && (size > 1) )
        {
            --size;
            --i;
        }

        // 转字符串
        string s = "";
        s.reserve(size);
        for(int i = size - 1; i >= 0; --i)
        {
            s += ('0' + ret[i]);
        }

        // 释放动态分配的内存
        delete[] ret;
        return s;
    }
};

四、代码详细分析

1. 特殊情况处理

if(num1 == "0" || num2 == "0")
    return "0";

如果 num1 或 num2 为 "0",则它们的乘积一定为 "0",直接返回即可。

2. 反转字符串

reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());

使用 std::reverse 函数将 num1 和 num2 反转,这样在后续计算中可以从低位(字符串的起始位置)开始处理。

3. 初始化结果数组

int size = num1.size() + num2.size();
int* ret = new int[size]();

建一个长度为 num1.size() + num2.size() 的整数数组 ret,并使用 () 进行值初始化,将数组元素都初始化为 0。

4. 逐位相乘

for(int i = 0; i < num1.size(); ++i)
{
    for(int j = 0; j < num2.size(); ++j)
    {
        ret[i + j] += (num1[i] - '0') * (num2[j] - '0');
    }
}

使用两层嵌套循环,将 num1 的每一位与 num2 的每一位相乘,并将结果累加到 ret 数组的相应位置。(num1[i] - '0') 和 (num2[j] - '0') 是将字符转换为对应的数字。

5. 处理进位

for(int i = 0; i < size - 1; ++i)
{
    ret[i + 1] += ret[i] / 10;
    ret[i] = ret[i] % 10;
}

遍历 ret 数组,将每一位的进位(ret[i] / 10)加到下一位,同时将当前位取模 10 得到该位的最终结果。

6. 去除前导零

int i = size - 1;
while( (ret[i] == 0) && (size > 1) )
{
    --size;
    --i;
}

从结果数组的最高位开始检查,如果该位为 0 且结果长度大于 1,则将长度减 1,继续检查前一位。

7. 转换为字符串

string s = "";
s.reserve(size);
for(int i = size - 1; i >= 0; --i)
{
    s += ('0' + ret[i]);
}

创建一个空字符串 s,并使用 reserve 方法预先分配足够的空间。然后从结果数组的最高位开始,将每一位转换为字符并添加到字符串 s 中。

8. 释放内存

delete[] ret;

由于 ret 是动态分配的数组,使用完后需要使用 delete[] 释放内存,避免内存泄漏。

五、复杂度分析

  • 时间复杂度:O ( m ∗ n ),其中 m mm 和 n nn 分别是 num1 和 num2 的长度。主要时间开销在于两层嵌套的循环进行逐位相乘。
  • 空间复杂度:O ( m + n ),主要空间开销在于存储中间结果的数组 ret

通过以上步骤,我们就可以实现两个大整数的乘法,并将结果以字符串形式返回。这种方法模拟了手工乘法的过程,避免了使用内置的大整数库和直接将输入转换为整数,适用于处理超出内置整数类型表示范围的大整数乘法问题。

以上就是C++基于字符串实现大数相乘问题的代码详解的详细内容,更多关于C++字符串实现大数相乘的资料请关注脚本之家其它相关文章!

相关文章

  • 解析C++类内存分布

    解析C++类内存分布

    本篇文章介绍了C++类内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承、虚函数存在的情况下
    2021-06-06
  • C++ Boost Pool超详细讲解

    C++ Boost Pool超详细讲解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C语言实现学生信息管理系统(单链表)

    C语言实现学生信息管理系统(单链表)

    这篇文章主要为大家详细介绍了C语言实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C++使用HTTP库和框架轻松发送HTTP请求

    C++使用HTTP库和框架轻松发送HTTP请求

    使用C++编程发送HTTP请求通常需要使用第三方的HTTP库或框架,本文主要介绍了C++使用HTTP库和框架轻松发送HTTP请求,感兴趣的可以了解一下
    2023-12-12
  • 详解C++标准库中处理正则表达式的类std::regex

    详解C++标准库中处理正则表达式的类std::regex

    std 是 C++ 标准库的命名空间,包含了大量标准的 C++ 类、函数和对象,这些类和函数提供了广泛的功能,包括输入输出、容器、算法、字符串处理等,这篇文章主要介绍了C++标准库中提供的用于处理正则表达式的类std::regex,需要的朋友可以参考下
    2024-03-03
  • C++实现插入排序对整数数组排序

    C++实现插入排序对整数数组排序

    这篇文章主要为大家详细介绍了C++实现插入排序对整数数组排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • C语言实现个人通讯录管理系统

    C语言实现个人通讯录管理系统

    这篇文章主要为大家详细介绍了C语言实现个人通讯录管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • QT .pro文件的实现

    QT .pro文件的实现

    本文主要介绍了QT .pro文件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • C++中的std::initializer_list使用解读

    C++中的std::initializer_list使用解读

    这篇文章主要介绍了C++中的std::initializer_list使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 在C语言中对utmp文件进行查找和写入操作的函数小结

    在C语言中对utmp文件进行查找和写入操作的函数小结

    这篇文章主要介绍了在C语言中对utmp文件进行查找和写入操作的函数小结,包括pututline()函数和getutline()函数以及getutid()函数,需要的朋友可以参考下
    2015-08-08

最新评论