高精度加减乘除

高精度

  1. 逆序存储数字
  2. 模拟的实现
  3. 考虑模拟细节(如零、前导零、负数、进位、借位、反转等)

高精度加法 O(n)

// C = A + B, 满足A >= 0, B >= 0
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(t);
    return C;
}

高精度减法 O(n)

注意:考虑A<B结果为负数的情况

// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> A, vector<int> B)
{
    vector<int> C;
    int t = 0; // 存储相减的结果和借位
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i] - (i < B.size()) * B[i];
        C.push_back((t + 10) % 10);
        t = (t < 0) * (-1);
    }
    // 去除前导零
    while (C.size() > 1 && !C.back()) C.pop_back();
    return C;
}
// 比较存储数字的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;
}

高精度乘低精度 O(n)

注意:考虑需要不停进位的情况

// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> A, int b)
{
    vector<int> C;
    if (!A.back() || !b) return (C.push_back(0), C); // A不含前导零
    int t = 0;
    // 如果t作为乘数相加非常大, 需要不停进位
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    // 如果含前导零的A,去除前导零
    // while (C.size() > 1 && C.back() ` 0) C.pop_back();
    return C;
}

高精度乘以高精度 O(n2)

注意:使用数组存储,注意每次循环的错位相加

// lena >= 0, lenb >= 0
void<int> multi(int a[], int b[], int c[], int lena, int lenb)
{
    for (int i = 0; i < lena; i ++ )
        for (int j = 0; j < lenb; j ++ )
        {
            c[j + i] += a[j] * b[i];
            if (c[j + i] >= 10)
            {
                c[j + i + 1] += c[j + i] / 10;
                c[j + i] %= 10;
            }
        }
    // 去除前导零
    int k = lena + lenb;
    while (k >= 0 && !c[k]) -- k;
    // 判断输出
    if (k < 0) cout << 0;
    while (k >= 0) cout << c[k -- ];
}

高精度除以低精度 O(n)

注意:兼容其他高精度算法,需从高位开始且翻转数组

// A / b = C ... r, A >= 0, b > 0
vector<int> div1(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()) C.pop_back(); // 去除第一位是0的情况
    return C;
}

低精度除法保留位数 O(n)

// a除以b保留前n为小数
void div2(int a, int b, int n)
{
    if (!n) 
    {
        cout << a / b;
        return;
    }
    string res;
    res.append(to_string(a / b) + '.');
    int t = (a % b) * 10;
    int k = 0; // 小数点位数
    while (k < n - 1)
    {
        res.append(to_string(t * 10 / b));
        t = (t  * 10) % b;
        k ++ ;
    }
    cout << res;
}
posted @ 2022-05-03 17:19  feiyucoder  阅读(32)  评论(0)    收藏  举报