高精度加法

高精度是什么意思

在计算机中,高精度的意思是指 一个数特别特别大,最大可以有 10的5次方 个 位数 ,注意是有这么多位数,而不是 10的五次方 大。


两个高精度数字的加法

下面来求两个超级超级大的数字相加。

本次实现两个数字均为正整数,求负数的会在高精度减法的时候讲到。


思路实现

我们先来模拟一下人类是怎么实现加法的。

在这里插入图片描述
首先是计算个位数,由于5 + 9 = 14 ,14 > 10 所以要进一位,个位是4。

在这里插入图片描述
同理后面思路一样。


代码实现

由于没有数据类型能够存这么大的数字,所以我们需要用到数组来存储每一位。

又由于 不能直接读取数字 将每一位放到数组中,所以我们得利用字符串先读取,然后再遍历字符串将每一位放到数组中。

所以我们先创建两个字符串,然后读取两个数字
在这里插入图片描述
接下来需要将字符串的每一位放到数组当中。

由于vector容器不需要自己手动记录 数组当中有效数据的个数,所以我们使用vector容器。

在这里插入图片描述

接下来遍历字符串,将每一位存到数组当中。

在这里插入图片描述
注意:字符串的每一位都是字符,所以在放到数组当中的时候一定要 减去 ‘0’(字符0).

这里你会发现我们是倒着存的,数字的个位放在了数组中的第一位。

这是因为由于数组后端插入值比较方便,在最高位进位时会方便很多。

接着将高精度加法封装成一个函数
在这里插入图片描述
这里的 auto 的意思是 编译器会自动 推断 变量的类型。

最后输出我们的数组C,由于最开始我们是倒着存的,所以我们需要倒着输出。

在这里插入图片描述

接着来看add函数
在这里插入图片描述
返回类型为 vector< int > 数组,函数参数为两个vector< int > 类型。

首先定义一个 vector< int > 作为结果, 最后会将该容器返回。
在这里插入图片描述
在刚才的思路中,我们模拟了人类加法的过程,由于在加法的过程中 会有进位,所以需要创建一个变量来存储进制。

在这里插入图片描述
这里的 t 的含义是 是上一位所进的位,由于个位 是最低位,所以刚开始的进位为0。

接下来就需要遍历两个数组中的每一位的数字。

在这里插入图片描述
这里需要关注的是循环的判断条件,意思是 下标 i 不能跑到 两个数组的大小中 较大的那一个的 外边。

接着将 t 加上 该位的值。
在这里插入图片描述
这里不能直接加上 下标 i 的值,需要判断一下 下标 i 有没有值,比如下面这个例子。

在这里插入图片描述
在这里插入图片描述
当 下标 i 走到这个地方的时候 ,此时 下面没有值,所以就不能加。

加完了之后,此时有两种情况,第一种是 t > 10,则需要进一位,然后插入 t % 10 ;第二种是 t < 10,则直接插入t。

对于这两种情况,我们不需要分类,不需要写if 语句,只需要直接插入 t % 10.
在这里插入图片描述
因为如果小于10的话 % 10 还是 不变的。

插入之后,由于 我们最初定义 t 的 含义为 上一位数的 进位,所以 最后需要 t /= 10。
在这里插入图片描述
如果t >= 10 那么 t 就会等于 1,t < 10那么就会等于0,那么到下一次 i 的时候就会加上上一次的进位。

写到这看似写完实则还差一步,我们来看下面这个例子。
在这里插入图片描述
这里我们模拟了倒着存放,其中根据for循环 i下标 最多循环到 9 这个位置,但是我们发现,最后还需要再进一位,所以 就需要 在最后 加上 t 这个进位。

当然前提得不是0,要不然结果最后开头会有个0.

最后返回我们的vector容器C即可。

在这里插入图片描述


可以做出的优化

add函数的参数换成引用

在这里插入图片描述
如果不使用引用的话,那么就会重新开辟一份空间,因为形参是实参的一份临时拷贝。

而由于引用是 别名,也就是操作的是原vector容器,所以就不会浪费额外的空间,当然算法题其实也没那么需要注意空间,只需要小于题目要求即可,但是还是引用好一点。


让函数 当中 的A容器的大小一定比 B的大

所以我们可以加上这条语句。
在这里插入图片描述
如果 B 数字比较长,那么就反着放调用,因为是加法,所以也不影响结果。

这样就保证了 我的 A一定 比 B 的长度要大,所以,下面的语句也可以进行修改。
在这里插入图片描述


t 放到循环的 判断条件上

在这里插入图片描述
这里最后的一条语句也可以换成下面的。
在这里插入图片描述

此时就算 i 下标不满足, t 如果不为0,也就是如果有进位的话,也会执行,for循环。

不过这里会加上 一个 if 判断,如果不加的话,会越界,因为 此时 i 已经不满足条件了。

所以这个优化也不能算优化,看个人喜好决定怎么书写。

完整代码:

#include <iostream>
using namespace std;
#include <vector>

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

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');
    
    auto C = add(A, B);
    
    for (int i = C.size()-1; i >= 0; i--) cout << C[i];
    
    return 0;
}

下面为不用 vector的代码

#include <iostream>
#include <string>
using namespace std;


const int N = 1e5+10;
int A[N], B[N], C[N], asz, bsz, csz;

string a, b;

void add(int A[], int& asz, int B[], int& bsz, int C[], int& csz)
{
    for (int i = 0, t = 0; i < asz || i < bsz || t; i++)
    {
        if (i < asz) t += A[i];
        if (i < bsz) t += B[i];
        C[csz++] = t % 10;
        t /= 10;
    }
}


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> a >> b;
    for (int i = a.size()-1; i >= 0; i--)  A[asz++] = a[i] - '0';
    for (int i = b.size()-1; i >= 0; i--)  B[bsz++] = b[i] - '0';
    add(A, asz, B, bsz, C, csz);
    
    for (int i = csz-1; i >= 0; i--) cout << C[i];
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值