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日

相关文章

  • javascript对JSON数据排序的3个例子

    JavaScript对JSON数据排序的3个例子 在JavaScript中,我们可以使用sort()方法对JSON数据进行排序。sort()方法是数组的一个原生方法,可以按照一定规则对数组进行排序。本文将通过三个例子详细讲解如何使用sort()方法对JSON数据进行排序。 例子1:按照数字大小排序 var data = [ { name: ‘John’, a…

    C 2023年5月23日
    00
  • PostgreSQL 实现将多行合并转为列

    下面是详细讲解”PostgreSQL 实现将多行合并转为列”的完整攻略。 背景 假设当前有如下一张表格table1,其中id列为主键,col_name列为需要转为列的字段名称,col_value列为需要转为列字段对应的值。 id col_name col_value 1 name John 1 age 30 1 gender Male 2 name Emil…

    C 2023年5月22日
    00
  • js数组与字符串常用方法总结

    JS数组与字符串常用方法总结 本篇攻略主要介绍 JavaScript 中数组和字符串的常用方法。 数组 1. 创建数组 数组可以通过以下方式进行创建: var arr1 = []; // 空数组 var arr2 = new Array(); // 空数组 var arr3 = [1, 2, 3]; // 带有元素的数组 2. 数组的常用方法 2.1 pus…

    C 2023年5月22日
    00
  • C语言指向常量的常量指针

    C语言中常量指针和指向常量的指针是两个不同的概念,而指向常量的常量指针则是将两者结合的一种指针类型。下面我将详细讲解该指针类型的使用攻略。 一、指向常量的常量指针定义 指向常量的常量指针是对一片存储区域的const限定,因此使用该指针进行间接访问时不能对存储区域进行修改操作。 指向常量的常量指针的定义格式如下: const int *const ptr; 其…

    C 2023年5月9日
    00
  • C++设计模式之简单工厂模式实例

    C++设计模式之简单工厂模式实例详解 简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。简单工厂模式定义了一个工厂类,它可以根据所传递的参数或配置文件的不同,返回不同类的实例。简单工厂模式具有简单易懂,适用范围广等特点,在实际开发中也得到了广泛应用。 简单工厂模式的结构 简单工厂模式包含三个主要…

    C 2023年5月22日
    00
  • 看面子选LCD —液晶面板A、B、C

    看面子选LCD —液晶面板A、B、C 在选择液晶面板时,除了考虑像尺寸和价格等常规因素,还需要谨慎评估其面板类型。面板的类型可以在宣传材料或数据表中找到。在液晶面板市场上,面板类型通常被标记为A、B或C类别,而且这些类别不仅影响面板的品质,而且会影响面板的价格。下面是一个详细的攻略来帮助你在A、B、C类别之间作出决策。 A、B、C 类面板的差异 三种类型面板…

    C 2023年5月22日
    00
  • C语言实现通讯录

    一、通讯录准备 1. 通讯录信息的准备 2. 通讯录功能的框架 3. 文件安排 二、实现通讯录的功能 1. 添加功能 2. 删除功能 3. 展示功能 4. 更改功能 5. 查找功能 6. 排序功能 三、总结 1.在main函数中,采用&的原因 2.在使用scanf函数时,为何某些参数不需要&,而有一些参数需要使用& 3.在添加功能中,…

    C语言 2023年4月18日
    00
  • C程序 检查一个数字是否为 Palindrome

    首先,需要明确Palindrome的定义:一个数字是Palindrome,当且仅当它的数字顺序倒过来后仍然相同。例如,121是Palindrome,而123不是Palindrome。 接下来,我们来介绍如何在C程序中检查一个数字是否为Palindrome。以下是完整的使用攻略: 步骤一:将数字转化为字符串 我们需要将要检查的数字转化为字符串,然后才能进行后续…

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