栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【Y总/算法基础课/学习笔记】高精度整数加法/减法/乘法/除法(含算法模板)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Y总/算法基础课/学习笔记】高精度整数加法/减法/乘法/除法(含算法模板)

目录
    • 高精度运算
      • 1. 算法基本思想
      • 2. 高精度运算算法模板(理解背诵)
      • 3. 应用:模板题
        • (1)高精度加法
        • (2)高精度减法
        • (3)高精度乘法
        • (4)高精度除法

高精度运算

Java 和 Python 不用考虑高精度运算,因为 Java 有大整数类,Python 数据默认是无限大,而 C++ 遇到超长位数的(例如有 1 0 6 10^6 106 位的整数)的加减乘除,并没有数据类型去匹配,也无法进行存储、运算,通常会出现数据溢出的情况,这时候就需要考虑使用高精度运算算法。

高精度运算,是指参与运算的数(加数,减数,因子等)范围大大超出了标准数据类型(整型,实型)能表示的范围的运算『例如,求两个 1 0 6 10^6 106 位的数的和』。这时,就要用到高精度算法了。本文的高精度运算的算法包括了加法、减法、乘法以及除法。

  • 高精度加法(A + B):两个 ≤ 1 0 6 ≤10^6 ≤106 位的数的和;
  • 高精度减法(A - B):两个 ≤ 1 0 6 ≤10^6 ≤106 位的数的差;
  • 高精度乘法(A * a):一个 ≤ 1 0 6 ≤10^6 ≤106 位的数乘以一个 ≤ 10000 ≤10000 ≤10000 的小整数所得的结果;
  • 高精度除法(A / a):一个 ≤ 1 0 6 ≤10^6 ≤106 位的数除以一个 ≤ 10000 ≤10000 ≤10000 的小整数所得的商和余数。

1. 算法基本思想
  • 算法思想:
    • 大整数的存储问题:我们将大整数的每一位存到数组里,并按照『个位 → 十位 → 百位 → . . . ... ...』的顺序依次存入数组,下标对应着『0 → 1 → 2 → . . . ... ...』,这是因为考虑到加法、乘法会存在 进位 ,在数组某位补上一位会比在数组最前面补上一位更容易。
    • 运算方法:模拟人的运算过程。
      • 高精度加法:从大整数的个位开始加,每一位加的过程看做为『 A i + B i + t A_i + B_i + t Ai​+Bi​+t』,『 t = 0 或 1 t = 0 或 1 t=0或1』 为被进位。若『 A i A_i Ai​』或者『 B i B_i Bi​』不存在,则将其看做为『 0 0 0』即可。
      • 高精度减法:前提保证『 A ≥ B A ≥ B A≥B』。从大整数的个位开始减,每一位减的过程看做为『 A i − B i − t A_i - B_i - t Ai​−Bi​−t』,『 t = 0 或 1 t = 0 或 1 t=0或1』 为被借位。这里有两种情况:一是『 A i − B i − t ≥ 0 A_i - B_i - t ≥ 0 Ai​−Bi​−t≥0』,直接减;二是『 A i − B i − t < 0 A_i - B_i - t < 0 Ai​−Bi​−t<0』,则需要借位,答案为『 A i − B i − t + 10 A_i - B_i - t + 10 Ai​−Bi​−t+10』。
      • 高精度乘法:只考虑『一个高精度大整数 A A A 乘以一个小整数 a a a』。从大整数的个位开始乘,每一位乘的过程看做为『 ( A i ∗ a + t ) % 10 (A_i *a + t)%10 (Ai​∗a+t)%10』,『 t t t』 为被进位,而下一位的被进位为『 t = ( A i ∗ a + t ) / 10 t=(A_i *a + t)/10 t=(Ai​∗a+t)/10』。
      • 高精度除法:只考虑『一个高精度大整数 A A A 除以一个小整数 a a a』。从大整数的最高位开始除,最高位除的过程看做为『 A i / a A_i /a Ai​/a,商为 r e s i res_i resi​,余数为 r i r_i ri​』;下一位除的过程看做『 ( r ∗ 10 + A i − 1 ) / a (r*10+A_{i - 1})/a (r∗10+Ai−1​)/a,商为 r e s i − 1 res_{i-1} resi−1​,余数为 r i − 1 r_{i-1} ri−1​』;以此类推可得最终大整数除以小整数的商和余数。
    • 建议结合代码来理解以上算法思路。

2. 高精度运算算法模板(理解背诵)

【高精度加法】

vector BigInt_add(vector &A, vector &B)
{
    if (A.size() < B.size()) return add(B, A);

    vector C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }

    if (t) C.push_back(t);
    return C;
}

【高精度减法】

// 判断是否 A >= B
bool cmp(vector &A, vector &B)
{
    if (A.size() != B.size()) return A.size() > B.size();

    for (int i = A.size() - 1; i >= 0; i -- )
        if (A[i] != B[i])
            return A[i] > B[i];

    return true;
}

// 计算 A - B,前提是 A ≥ B
vector BigInt_sub(vector &A, vector &B)
{
    vector C;
    for (int i = 0, t = 0; i < A.size(); i ++ )
    {
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);  // 综合了两种情况
        if (t < 0) t = 1;
        else t = 0;
    }
	
	// 由于输出的位数是与 A 相同的,可能存在前导 0 ,因此需要循环判断一下删除前导 0 
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

【高精度乘法】

vector BigInt_mul(vector &A, int b)
{
    vector C;

    int t = 0;
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();

    return C;
}

【高精度除法】

vector BigInt_div(vector &A, int b, int &r)
{
    vector C;
    r = 0;
    for (int i = A.size() - 1; i >= 0; i -- )
    {
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    reverse(C.begin(), C.end());
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}
3. 应用:模板题 (1)高精度加法

AcWing 791. 高精度加法

【不压位 - C++代码】

#include 
#include 

using namespace std;

vector BigInt_add(vector &A, vector &B)
{
    if (A.size() < B.size()) return BigInt_add(B, A);

    vector C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }

    if (t) C.push_back(t);
    return C;
}

int main()
{
    string a, b;
    vector A, B;
    cin >> a >> b;
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

    auto C = BigInt_add(A, B);

    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
    cout << endl;

    return 0;
}

【压 9 位 - C++代码】

#include 
#include 

using namespace std;

const int base = 1000000000;

vector BigInt_add(vector &A, vector &B)
{
    if (A.size() < B.size()) return BigInt_add(B, A);

    vector C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % base);
        t /= base;
    }

    if (t) C.push_back(t);
    return C;
}

int main()
{
    string a, b;
    vector A, B;
    cin >> a >> b;

    for (int i = a.size() - 1, s = 0, j = 0, t = 1; i >= 0; i -- )
    {
        s += (a[i] - '0') * t;
        j ++, t *= 10;
        if (j == 9 || i == 0)
        {
            A.push_back(s);
            s = j = 0;
            t = 1;
        }
    }
    for (int i = b.size() - 1, s = 0, j = 0, t = 1; i >= 0; i -- )
    {
        s += (b[i] - '0') * t;
        j ++, t *= 10;
        if (j == 9 || i == 0)
        {
            B.push_back(s);
            s = j = 0;
            t = 1;
        }
    }

    auto C = BigInt_add(A, B);

    cout << C.back();
    for (int i = C.size() - 2; i >= 0; i -- ) printf("%09d", C[i]);
    cout << endl;

    return 0;
}

(2)高精度减法

AcWing 792. 高精度减法

【C++代码】

#include 
#include 

using namespace std;

bool cmp(vector &A, vector &B)
{
    if (A.size() != B.size()) return A.size() > B.size();

    for (int i = A.size() - 1; i >= 0; i -- )
        if (A[i] != B[i])
            return A[i] > B[i];

    return true;
}

vector BigInt_sub(vector &A, vector &B)
{
    vector C;
    for (int i = 0, t = 0; i < A.size(); i ++ )
    {
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0) t = 1;
        else t = 0;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

int main()
{
    string a, b;
    vector A, B;
    cin >> a >> b;
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

    vector C;

    if (cmp(A, B)) C = BigInt_sub(A, B);
    else C = BigInt_sub(B, A), cout << '-';

    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
    cout << endl;

    return 0;
}

(3)高精度乘法

AcWing 793. 高精度乘法

【C++代码】

#include 
#include 

using namespace std;


vector BigInt_mul(vector &A, int b)
{
    vector C;

    int t = 0;
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();

    return C;
}


int main()
{
    string a;
    int b;

    cin >> a >> b;

    vector A;
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');

    auto C = BigInt_mul(A, b);

    for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);

    return 0;
}

(4)高精度除法

AcWing 794. 高精度除法

【C++代码】

#include 
#include 
#include 

using namespace std;

vector BigInt_div(vector &A, int b, int &r)
{
    vector C;
    r = 0;
    for (int i = A.size() - 1; i >= 0; i -- )
    {
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    reverse(C.begin(), C.end());
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

int main()
{
    string a;
    vector A;

    int B;
    cin >> a >> B;
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');

    int r;
    auto C = BigInt_div(A, B, r);

    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];

    cout << endl << r << endl;

    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1001649.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号