高精度除法(高精度除以低精度)模版,代码思路分析(C++版本)

169 阅读4分钟

1.除法的题目和说明

下面的这个实际上是一个基础版本的这个高精度的除法,不是非常的严谨,但是也是所有的高精度除法里面最简单的;

但是我觉得这个对于小白而言就够了,如果你认为自己掌握好了再去掌握其他的也可以的;

其他的高精度的除法,我也是见过的,下面的这个A/B里面的这个B实际上是10的9次方,因此这个题目实际上是高精度除以我们的低精度,也有一些这个进阶的题目是高精度除以高精度的,就是两个数据的这个范围都是非常大的;

还有的事高精度除以低精度,但是需要你去同时计算出来这个结果和余数,也就是商和余数都需要计算出来;

上面提到的两个进阶的题目都是比我们的这个下面的洛谷的题目简单的;

image-20250717201536860

2.计算的过程

下面的这个是截取的比特老师的板书,演示的这个除法的计算的过程,以及这个整体的商我们是如何一步一步的进行处理的;(下面的这个存在笔记,这个案例的结果余数应该是19,下面写成了29);

在下面的这个计算的过程当中,因为这个除数是45,我们刚开始使用这个1进行测试,但是发现太小了,接下来使用12进行测试,发现还是太小了,接下来使用这个123进行测试,这个时候可以进行这个正确的处理;

这个时候我们的商的那一位2就是使用的123对于45除法运算的结果,剩下的这个就是我们的33,也就是取模运算的结果;

至于这个从1到12到123这个过程,其实就是乘上10然后加上新的位上面的数字的过程;

image-20250717131656061

3.代码分析

下面的这个就是我们的高精度除法代码的模版

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

typedef long long LL;

int a[N], b, c[N];
int la, lc;

// 高精度除法的模板 - c = a / b (高精度 / 低精度)
void sub(int c[], int a[], int b)
{
    LL t = 0; // 标记每次除完之后的余数
    for(int i = la - 1; i >= 0; i--)
    {
        // 计算当前的被除数
        t = t * 10 + a[i];
        c[i] = t / b;
        t %= b;
    }

    // 处理前导 0
    while(lc > 1 && c[lc - 1] == 0) lc--;
}

int main()
{
    string x; cin >> x >> b;
    la = x.size();

    for(int i = 0; i < la; i++) a[la - 1 - i] = x[i] - '0';

    // 模拟除法的过程
    lc = la;
    sub(c, a, b); // c = a / b

    for(int i = lc - 1; i >= 0; i--) cout << c[i];
 

    return 0;
}

1)因为我们上面已经解释了,这个是是高精度除以这个低精度的,因此原本这个高精度里面无论是这个加法减法乘法,我们都是使用的三个数组,但是因为这个除法运算里面的这个除数就是一个低精度数据,我们使用long long就可以表示,因此这个只需要两个数组即可,一个存放我们的这个高精度的被除数,还有一个即使存放我们的这个结果;

2)定义输出的这个字符串,也是一个,因为这个是低精度的,我们不需要进行这个数据和字符串之间的这个转换的过程;

3)for循环也变成了一个,之前的是两个都需要从高精度转换成为这个字符串,但是在我们的这个问题里面,只有一个高精度的数据,因此只需要进行一次转换即可,这个转换的规则和之前的加减法里面是没有任何的这个区别的;

4)对于这个除法的过程,la直接给了这个lc,这个主要是因为进行这个除法运算之后,我们的这个结果的位数不可能超过这个被除数的位数;

5)接下来调用这个sub函数执行这个除法的过程,在这个除法的函数里面,处理前导0的这个思路是没有发生变化 的,t表示的是我们的每一次运算之后的这个余数,每一次这个t的更新就是乘以10加上这个当前位上面的数字;

这个可以回想一下之前的思路分析里面的这个1到12 到123的这个过程,和我们的这个代码就是对应起来的,这个c[i]=t/b这个就是除法运算,也就是求商的过程,t%=b就是处理的我们的这个运算的余数,放到我们的对应的位数上面去即可;