高精度加减法

104 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情

如何存储一个大数据 : 把一个大数据放到数据当中去

image-20221029121449464

为什么这样存储

原因是两个数相加或者相乘的时候,会产生进位,此时我们要在高位补上一个数,在数组后面插入一个数比在数组的前面插入一个数容易,如果在前面插入一个数,所有的数都要向后移一位

高精度加法

//C = A + B, A >= 0, B >= 0  其中低下标存的是数据的低位
vector<int> add(vector<int>& A, vector<int>& B)
{
    vector<int> C;//存放相加结果
    int carry = 0;//进位
    for (int i = 0; i < A.size() || i < B.size(); i++)
    {
        //通过判断下标i ,是否在A,B中是有效位置,一遍通过
        //ans = A[i] + B[i] + carry
        int ans = carry;//本轮计算结果
        if (i < A.size()) ans += A[i];
        if (i < B.size()) ans += B[i];
        C.push_back(ans % 10);
        carry = ans / 10;//进位
    }
    if (carry == 1)//最后看一下最高位有没有进位,有进位就要补1
        C.push_back(1);
​
    //123+456 = 579  最后C中存储的就是:975
    return C;
}

写法2:保证A数组是更长的数组,并且直接利用进位数,不用再定义一个变量

vector<int> add(vector<int> &A, vector<int> &B)
{
    //保证A的长度是更长的,所以下面for可以省略一个条件:i<B.size() 数组低下标是低位 
    if (A.size() < B.size()) return add(B, A);
    
    vector<int> C;
    int carry = 0;//利用进位数,不用再定义一个变量存储
    for (int i = 0; i < A.size(); i ++ )
    {
        carry += A[i]; //A数组是更长的
        if (i < B.size()) carry += B[i];
        C.push_back(carry % 10);
        carry /= 10;
    }
    
    if (carry) C.push_back(carry);
    return C; 
}

高精度减法:

t:表示是否要向上一位借位,注意:我们这里要保证是大数 - 小数 ,即要保证:要保证A>=B

  • 如果A<B 就去计算B-A 然后最后结果加个负号

image-20221029152046571

  • 假设计算结果为ans, 如果ans>=0 ,返回的是ans, 如果ans<0:返回的是ans+10
  • 可以合并成一种情况: 返回 (ans+10)%10

注意:最后可能需要把前导0去掉,如:123-120=3, 最后数组存放的是300 (倒着存),需要把前导0去掉,变成3


判断A数组和B数组哪个更大

//判断是否有A>=B
bool cmp(vector<int>& A, vector<int>& B)
{
    if (A.size() != B.size())  
        return A.size() > B.size();
    //二者长度相等,需要判断谁更大,从数的高位开始判断  例如:判断999998的大小
    //数组中低下标存的是低位,所以倒着比较
    for (int i = A.size() - 1; i >= 0; i--)
    {
        if (A[i] != B[i])
            return A[i] > B[i];
    }
    return true;//二者相等
}

高精度减法

// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int>& A, vector<int>& B) //调用时要保证A数组更大
{
    vector<int> C;
    int t = 0;//借位
    for (int i = 0; i < A.size(); i++)
    {
        //直接复用借位变量,当前这一位的计算值就是:t = A[i] - B[i] - t
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
​
        //如果此时的计算结果t>=0的话,就是t本身,如果<0的话,就返回t+10 (向上一位借位)
        //上面两种情况合二为一: (t + 10) % 10
        C.push_back((t + 10) % 10);
        if (t < 0) //需要向上一位借位
            t = 1;
        else
            t = 0;
    }
    //去掉前导0
    //如果最后结果是0的话,就要保留这个0,所以必须保证C.size() > 1
    while (C.size() > 1 && C.back() == 0)
        C.pop_back();
    return C;
}