高精度减法

发布时间 2023-10-13 22:25:33作者: grave_master

一、算法描述

要实现两个高精度数的减法,和高精度加法一样都是模拟竖式计算的过程,主要就是解决以下两个问题。

谁大谁小?

由于这两个数字都很大,但是不知道谁更大,所以要先判断哪个数更大,思路如下:

  • 判断这两个数谁的位数更大,位数更大的自然更大。

  • 如果位数不相同,从最高位开始往低位遍历,判断两个数字是否相等,更大的那个原本的数字也更大。

  • 如果都一样,即默认是前面一个数更大,并不影响后面的操作。

代码如下:

bool cmp(vector<int> &A, vector<int> &B)
{
    if (A.size() != B.size())   return A.size() > B.size();
    else
        for (int i = A.size() - 1; i >= 0; --i)
            if (A[i] != B[i])
                return A[i] > B[i];
    return true;
}

如何计算?

解决了正负问题,现在来解决如何实现大数减小数。

  • 这依然是一个模拟问题,思考如何列竖式计算两个数的减法。

  • 从小到大遍历第一个数(第一个数不小),t += A[i],如果第二个数在当前位数还有数,减去该数,t -= B[i],还有别忘了处理前一位计算可能产生的借位。

  • 将计算结果加入到答案数组中,由于t有两种情况,t >= 0 || t < 0,所以可以统一处理:(t + 10) % 10

  • t < 0时,就是产生了借位,令t = -1,方便下一轮处理,否则令t = 0表示没有产生借位。

  • 最后还需要注意,如果两个数差距非常小,即最后的结果产生了很多前导 \(0\) ,此时我们需要消除,因为输出的时候不需要这些前导 \(0\)

  • 但是也要注意如果两个数相等,那么最后的结果是 \(0\) ,要保留最后一个 \(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];
        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;
}

说明:

  • \(|A| + |B|\)可以转化为 \(A + B、A - B、B - A、-(A + B)\) 这四种情况,都是可以用高精度加减法解决的,只需要特殊处理一下输入即可,所以当前讨论的都是正整数。

二、题目描述

给定两个正整数(不含前导 \(0\) ),计算它们的差,计算结果可能为负数。

输入格式

共两行,每行包含一个整数。

输出格式

共一行,包含所求的差。

数据范围

\(1≤整数长度≤10^5\)

输入样例:

32
11 

输出样例:

21 

三、题目来源

AcWing算法基础课-792.高精度减法

四、源代码

#include <iostream>
#include <vector>

using namespace std;

const int N = 100010;

bool cmp(vector<int> &A, vector<int> &B)
{
    if (A.size() != B.size())   return A.size() > B.size();
    else
        for (int i = A.size() - 1; i >= 0; --i)
            if (A[i] != B[i])
                return A[i] > B[i];
    
    return true;
}

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];
        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;
    cin >> a >> b;
    
    vector<int> 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<int> C;
    if (cmp(A, B))  C = sub(A, B);
    else
    {
        cout << "-";
        C = sub(B, A);
    }
    
    for (int i = C.size() - 1; i >= 0; --i) cout << C[i];
    
    return 0;
}