C++实现大数相乘算法

C++ 实现大数相乘算法

当我们需要计算两个超出计算机整数范围的大数相乘时,传统的计算方法已经无法满足需求,因此需要寻找一种适合大数相乘的算法。本文将介绍一种针对大数相乘的算法 - Karatsuba乘法,并使用C++语言进行实现。

Karatsuba 乘法的原理

Karatsuba 乘法的基本思想是将两个大数a和b分别划分为高位和低位,进而利用递归的方法将相乘转化为更小的数的相乘,最后统一合并得到最终结果。

假设a和b的长度相同,而且都是偶数,假设a实际上可以拆分为a0和a1两份,b可以拆分为b0和b1两份,即:

a = a0 * 10 ^ (n/2) + a1

b = b0 * 10 ^ (n/2) + b1

根据这个公式我们可以推导出Karatsuba算法的公式:

a * b = (a0 * 10 ^ (n/2) + a1) * (b0 * 10 ^ (n/2) + b1)

    = a0 * b0 * 10^n + (a0 * b1 + a1 * b0) * 10^(n/2) + a1 * b1

这样我们就将一个大的乘法问题转化为3个小的乘法问题,并且它们的结果都可以通过加、减的计算得出。同时这个算法只需要递归两次,即可得出结果。

Karatsuba乘法的优点在于它的运算次数比传统的算法要少,因此可以大大提高计算效率。

C++ 实现

下面是使用C++实现Karatsuba算法的代码:

#include<iostream>
#include<cstring>
using namespace std;

string add(string a, string b) {
    if(a.length() < b.length()) swap(a, b);
    int alen = a.length(), blen = b.length();
    int carry = 0;  // 进位 
    string res = "";
    for(int i=alen-1, j=blen-1; i>=0; i--, j--) {
        int k = i-j-1;
        int sum = (j>=0 ? (b[j]-'0') : 0) + carry + (a[i]-'0');
        res = char(sum % 10 + '0') + res;
        carry = sum / 10;
    }
    if(carry) res = char(carry+'0') + res;
    return res;
}

string sub(string a, string b) {
    int alen = a.length(), blen = b.length();
    int jw = 0;  // 借位 
    string res = "";
    for(int i=alen-1, j=blen-1; i>=0; i--, j--) {
        int k = i-j-1;
        int v = a[i] - jw - (j>=0 ? b[j]-'0' : 0);
        if(v < 0) {
            v += 10;
            jw = 1;
        } else {
            jw = 0;
        }
        res = char(v+'0') + res;
    }
    while(res[0] == '0' && res.length() > 1) res.erase(0,1);  // 去掉前导0 
    return res;
}

string karatsuba(string a, string b) {
    int alen = a.length(), blen = b.length();
    if(alen < blen) {
        swap(alen, blen);
        swap(a, b);
    }

    if(alen == 0) return "0";
    if(alen == 1) return to_string((a[0]-'0') * (b[0]-'0'));

    int llen = alen >> 1, rlen = alen - llen;
    string a0 = a.substr(0, llen), a1 = a.substr(llen, rlen);
    string b0 = b.substr(0, min(blen, llen)), b1 = b.substr(min(blen, llen), max(0, blen-llen));
    string z0 = karatsuba(a1, b1), z1 = karatsuba(add(a0, a1), add(b0, b1)), z2 = karatsuba(a0, b0);

    string res = add(z2, add(z0, sub(z1, add(z2, z0))));
    while(res[0] == '0' && res.length() > 1) res.erase(0, 1);  // 去掉前导0
    return res;
}

int main() {
    string a, b;
    while(cin >> a >> b) {
        string res = karatsuba(a, b);
        cout << res << endl;
    }
    return 0;
}

代码中我们定义了Karatsuba算法的 karatsuba 函数,用来实现大数的相乘。同时我们还定义了加法 add 和减法 sub 的函数,这是因为在Karatsuba算法的实现中我们需要将大数的相加和相减。程序的输入为两个大数,即字符串类型的 ab,程序的输出为两个大数的乘积,即字符串类型的 res

示例

示例1

输入:

12345678901234567890
10101010101010101010

输出:

12499999991234567910027182807451020480

示例2

输入:

9999999999
8888888888

输出:

88888888871111111112

总结

本文介绍了Karatsuba乘法的基本原理,同时使用C++实现了该算法。本文同时提供了两个用例来说明算法的正确性。这个算法在大数相乘的场景下应用广泛,可以帮助我们提高相乘的计算效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++实现大数相乘算法 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C语言之详解静态变量static

    C语言之详解静态变量static 在C语言中,关键字static可以用于修饰全局变量,局部变量和函数,其作用分别如下: 1. 修饰全局变量 在全局变量前加上static关键字,表示该变量具有静态存储期和静态链接属性。 在同一文件中的其他函数中不能访问该变量。 只能被定义变量的函数访问。 被初始化为0,除非在定义时显式初始化。 static int a; //…

    C 2023年5月24日
    00
  • Win11使用USB或type-c耳机音量默认100%怎么解决?

    当在 Windows 11 中使用 USB 或 Type-C 耳机时,可能会发现音量默认为 100% ,这可能会给你带来一些不便。这种情况可以通过以下方式解决: 1. 禁用默认通讯设备 Windows 中默认会将通讯设备(如耳机麦克风)设置为默认设备,这可能会导致音量设置失效。解决方法是: 在任务栏上右键单击音量图标,选择““声音”选项。 在弹出的“声音”设…

    C 2023年5月23日
    00
  • C语言超全面define预处理指令的使用说明

    下面是“C语言超全面define预处理指令的使用说明”的完整攻略。 什么是define预处理指令 在C语言中,define是预处理指令之一,用于定义宏。 定义一个宏可以简化代码,使代码更易于阅读和维护。宏可以代替复杂的代码,让程序员在撰写代码时省去重复劳动。 如何使用define预处理指令 定义常量 可以使用define定义一个常量,如下面的代码: #def…

    C 2023年5月23日
    00
  • C语言小项目计时器的实现思路(倒计时+报警提示)

    C语言小项目计时器的实现思路(倒计时+报警提示) 思路概括 计时器的实现思路可以分为三个部分: 用户输入倒计时的时间,程序将其保存下来。 程序不断地循环检查当前时间与开始时间之间的差值是否大于等于用户设定的时间,当差值达到要求时,触发报警提示。 用户可以选择中途取消倒计时。 具体实现 1. 用户输入倒计时的时间 用户需输入倒计时的时间,可以通过scanf函数…

    C 2023年5月23日
    00
  • C语言自动生成enum值和名字映射代码

    以下是详细讲解“C语言自动生成enum值和名字映射代码”的完整攻略: 背景 在C语言中,枚举类型(enum)是一个非常常用的数据类型。在实际的编程过程中,我们常常需要将枚举类型的变量转换成其对应的字符串表示或者将字符串表示转换成枚举类型的变量。手动编写这样的代码往往非常繁琐且容易出错,因此我们需要一种自动生成这样代码的工具。 工具 在这里,我们推荐使用开源工…

    C 2023年5月24日
    00
  • javascript表单域与json数据间的交互

    下面是关于“javascript表单域与json数据间的交互”的完整攻略。 1. 什么是JSON? JSON(JavaScript Object Notation)是一种轻量级数据交换格式,原本用来代替XML,现在已成为一种独立的数据格式。它以键/值对的形式来表示数据,常用于传输数据,在客户端和服务器之间进行数据交互。 JSON 格式的数据可以是文本、数字、…

    C 2023年5月23日
    00
  • C语言 数组指针详解及示例代码

    C语言 数组指针详解及示例代码 什么是指针 指针是一种变量,它存储了一个地址。本质上,指针就是一个整数,但是它的类型与所指向对象的类型相同。在C语言中,我们可以通过指针来访问内存中的数据,或者在函数间传递指针来避免在函数之间进行大量的数据复制。 什么是数组指针 数组指针是指向数组的指针。与数组名类似,数组指针也可以被认为是第一个元素的地址。因此,当我们对数组…

    C 2023年5月24日
    00
  • VC实现ODBC数据库操作实例解析

    VC实现ODBC数据库操作实例解析 什么是ODBC ODBC是开放数据库连接(Open Database Connectivity)的简称。它提供了一种标准的接口方式,使得应用程序可以通过一组标准的API函数与各种数据库打交道。ODBC是由微软公司所提出、在1992年获得了国际标准的接口规范,因此,ODBC接口已经成为了连接各种不同数据库标准的事实标准。一般…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部