1. 概念

当两个正数相加时,可能会超出其类型的最大范围。当两个负数相加时,可能会超出其类型的最小范围。当两个数相乘时,依旧可能会超出其类型所能表示的最大范围。

2. 代码模板

2.1. 高精度加法模板

从个位开始,对两个数进行相加,假设当前位被加数是Ai,当前位加数是Bi;如果Ai+Bi>10,产生进位t为1,则在下一轮两数相加时额外再加上1;反之则不用。而结果中的每一位都是(Ai+Bi+t)%10。重复直到两个数的每个位都相加为止。

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

    vector<int> 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;
}

2.2. 高精度减法模板

从个位开始,对两个数进行相减,假设当前位被减数是Ai,当前位减数是Bi;如果Ai-Bi>0,直接算Ai-Bi即可;反之,则需要向前面进行借位,借位后借位t为1,Ai-Bi+10就是当前结果, 而前面一位数的减法结果为Ai-Bi-t。重复直到两个数的每个位都相减为止。

vector<int> sub(vector<int> &A, vector<int> &B)
{
    vector<int> 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;
}

2.3. 高精度乘低精度

从个位开始,对两个数进行相乘,假设当前位被乘数是Ai,乘数是b;那么当前乘法结果为(Aixb)%10,而进位结果t为(Aixb)/10,而前面一位数的乘法结果为(Aixb+t)%10。重复直到被乘数的全部位都与乘数相乘为止。

vector<int> mul(vector<int> &A, int b)
{
    vector<int> 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;
}

2.4. 高精度除以低精度

从最高位位开始,对两个数进行相除,假设当前位被除数是Ai,除数是b;那么当前除法结果为Ai/b,而余数为Ai%b,而后面一位数的被除数应该是Ai%b*10+A(i+1)。重复直到被除数的全部位都与除数相除为止。

vector<int> div(vector<int> &A, int b, int &r)
{
    vector<int> 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. 例题

3.1. 791. 高精度加法 - AcWing题库

#include <iostream>
#include <vector>

using namespace std;

// C = A + B
vector<int> add(vector<int> &A, vector<int> B)
{
    vector<int> C;
    // 进位
    int t = 0;
    for(int i = 0; i < A.size() || i < B.size(); i++)
    {
        if(i < A.size()) t += A[i];
        if(i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    if(t) C.push_back(1);
    return C;
}

int main()
{
    // a,b可能极大,无法用整数类型保存,因此使用string接收
    string a, b;
    
    cin >> a >> b; // a = "12345"
    
    // 使用数组保存每一位的值
    vector<int> A, B;
    
    // 尾插法方便计算
    for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0'); // A = [5, 4, 3, 2, 1]
    for(int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
    
    // auto编译器会自动推断返回类型
    auto C = add(A, B);
    
    for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
    
    return 0;
}

3.2. 792. 高精度减法 - AcWing题库

#include <iostream>
#include <vector>

using namespace std;

// 判断A是否大于等于B
bool cmp(vector<int> &A, vector<int> &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;
}

// C = A - B
vector<int> sub(vector<int> &A, vector<int> &B)
{
    vector<int> 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;
    }
    
    // 删除前导0
    while(C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main()
{
    // a,b可能极大,无法用整数类型保存,因此使用string接收
    string a, b;
    
    cin >> a >> b; // a = "12345"
    
    // 使用数组保存每一位的值
    vector<int> A, B;
    
    // 尾插法方便计算
    for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0'); // A = [5, 4, 3, 2, 1]
    for(int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
    
    // auto编译器会自动推断返回类型
    // 判断A和B谁大,A>B直接算,A<B则结果为-(B-A)
    if(cmp(A, B)) 
    {
        auto C = sub(A, B);
        for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
    }
    else
    {
        auto C = sub(B, A);
        printf("-");
        for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
    }
    
    return 0;
}

3.3 793. 高精度乘法 - AcWing题库

#include <iostream>
#include <vector>

using namespace std;

// C = A * B
vector<int> mul(vector<int> &A, int b)
{
    vector<int> 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;
    }
    // 删除前导0
    while(C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main()
{
    // a可能极大,无法用整数类型保存,因此使用string接收
    string a;
    int b;
    
    cin >> a >> b; // a = "12345"
    
    // 使用数组保存每一位的值
    vector<int> A;
    
    // 尾插法方便计算
    for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0'); // A = [5, 4, 3, 2, 1]
    
    // auto编译器会自动推断返回类型
    auto C = mul(A, b);
    
    for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
    
    return 0;
}

3.4. 794. 高精度除法 - AcWing题库

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// A / B,商是C,余是r
vector<int> div(vector<int> &A, int b, int &r)
{
    vector<int> C;
    
    // 余位
    r = 0;
    for(int i = A.size() - 1; i >= 0; i--)
    {
        // 每往后走一位,前面数的权值*10
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    
    reverse(C.begin(), C.end());
    
    // 删除前导0
    while(C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main()
{
    // a可能极大,无法用整数类型保存,因此使用string接收
    string a;
    int b;
    
    cin >> a >> b; // a = "12345"
    
    // 使用数组保存每一位的值
    vector<int> A;
    
    // 尾插法方便计算
    for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0'); // A = [5, 4, 3, 2, 1]
    
    // auto编译器会自动推断返回类型
    int r;
    auto C = div(A, b, r);
    
    for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
    cout << endl << r <<endl;
    
    return 0;
}

4. 扩展

如果进行操作的两个数不全是正数,其实只需要在对操作数上加上绝对值即可,然后再将所对应的+-进行转换,例如当B为负数时,A+B=|A|-|B|; A-B=|A|+|B|;而乘除只需要修改修改其最后的符号即可。

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]