算法基础课:高精度


高精度

高精度大数存储

因为运算时涉及到进位,故而当输入一个大整数,将其存储在可变数组时,需要倒过来存储。

如:123456789,存储为[9,8,7,6,5,4,3,2,1],进位时push_back(),删除时pop_back()

C++实现

// 大数存储
#include
#include

using namespace std;

int main () {
    string a, b;	// 作为大数的输入
    vector A, B;	// 使用2个动态数组存储
    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');

    return 0;

}

高精度加法

算法

  • 模拟加法的过程,通过进位的t,实现每一位的加法
  • t % 10 即此时的余在这一位的数
  • t / 10,为 1 则进位,为 0 则无进位
  • 在A、B最后一位加法结束后,判断有没有进位,即可返回加法后的结果

C++实现

vector add(vector &A, vector &B) {
    vector 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(t);

    return C;
}

高精度减法

算法

  • 先通过 cmp() 比较两个动态数组谁大谁小,再通过 sub() 函数进行减法操作
  • 传入sub()的数,通过判断大小,始终是用大减小
  • 先将当前位的A[i] - t,减掉借位的值,如果没有借位即为减 0借了位则减 1,再将 t赋值为它去具体的减当前位的B[i]
  • 如果B还有值,那么这一位的C[i] 存的是 t - B[i] 的值 加上 10(模) 再取模,即如果 t小于 B[i] 那么就从上一位借位,如果t 大于 B[i] ,这个 + 10 % 10 的操作还是原来的值
  • 如果 t - B[i] < 0,即从上一位借位了,那么把t 置为 1,在下一步的时候 A[i + 1] 要减去1,如果其 大于 0,则t = 0,表示没有借位。
  • 最后再把结果动态数组C的高位的0去掉(因为借位后,可以高位会置为 0)

C++实现

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

高精度乘法

算法

  • 这里是大整数 * 普通整数
  • 令 t = A[i] * b,C为这里的乘机取余 t % 10,进位 t /= 10

C++实现

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

高精度除法

算法

  • 使用一个大整数除以一个普通整数
  • 模拟除法过程,从高位除起,余数 * 10 和 下一位相加 再除以 b
  • 具体的操作为 r为上一位的余数,到操作位时:r = r * 10 + A[i]
  • 这一位的除的积为 r / b,得到余数为 r %= b

C++实现

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