C++ 基于vector的高精度算法 思路+代码(加减乘除)

前言

在我个人看来,其实高精度算法就是把我们手算加减乘除的思维过程模拟了一边,所以如果不记得的话不如手算一遍,看看自己是如何处理每个数字的。

一、高精度加法

代码

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

// 定义一个函数实现大整数加法
vector<int> add(vector<int> a, vector<int> b){
    if(a.size() < b.size()) return add(b, a); // 确保a的长度不小于b的长度

    vector<int> temp;
    int carry = 0; // 进位,初始为0
    for(int i = 0; i < a.size(); i++){
        if(i < b.size()) carry += b[i]; // 如果b还有位数,加上对应位的数字
        carry += a[i]; // 加上a对应位的数字
        temp.push_back(carry % 10); // 将个位数字加入结果中
        carry /= 10; // 更新进位
    }

    if(carry) temp.push_back(carry); // 最后如果还有进位,加入结果中

    // 去除前导0
    while(temp.size() > 1 && temp.back() == 0) temp.pop_back(); // 去除前导0

    reverse(temp.begin(), temp.end()); // 将结果反转,使得高位在前

    return temp;
}

int main(){
    string A, B;
    vector<int> a, b;
    
    cin >> 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');

    // 调用 add 函数进行大整数加法
    vector<int> result = add(a, b);

    // 输出相加的结果
    for(int i = 0; i < result.size(); i++) cout << result[i];

    return 0;
}

二、高精度减法

代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 比较a和b的大小,若为true,则表示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;
}

// 实现两个非负整数的减法操作
vector<int> sub(vector<int> a, vector<int> b) {
    vector<int> temp;
    int t = 0;
    for (int i = 0; i < a.size(); i++) {
        t = a[i] - t; // 从a的当前位减去借位
        if (i < b.size()) t -= b[i]; // 若b还有位数,则继续减去b的对应位
        temp.push_back((t + 10) % 10); // 将结果加入到temp中
        if (t < 0) t = 1; // 如果需要借位,则将t设为1
        else t = 0; // 否则不需要借位
    }

    // 去除temp末尾的多余0
    while (temp.size() > 1 && temp.back() == 0) temp.pop_back();

    reverse(temp.begin(), temp.end()); // 将temp翻转得到最终结果
    return temp;
}

int main() {
    string A, B;
    vector<int> a, b;
    cin >> 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> result;
    // 如果a大于b,则直接进行减法运算
    if (cmp(a, b)) {
        result = sub(a, b);
    }
    // 如果a小于b,则输出负号,并进行减法运算
    else {
        result = sub(b, a);
        cout << "-";   
    }

    // 输出最终的结果
    for (int i = 0; i < result.size(); i++) cout << result[i];

    return 0;
}

三、高精度乘法

1.高精度乘以低精度

思路

假设我们要求345x67

先来理解一个十进制数的本质
345=3x100+4x10+5

那么
345x67
=(3x100+4x10+5)x67
=(3x100x67)+(4x10x67)+(5x67)

所以我们求出5x67=335之后,很容易能想到,个位只会保留5,而330会加到更高位上。
即4x10x67要加上330

都除以10,就得到4x67加上33

所以可以得出,计算过程为:
从低位开始,获取A的一位,与b相乘,结果的个位留在这一位,结果除以10后加到下一位
这样循环直到A的最高位

手算过程如下图:
其中蓝色小圆圈保留在该位,横线进入下一位。
在这里插入图片描述

代码

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

// 定义一个函数 mul,用于实现大整数乘法
// 参数 a: 存储大整数的向量
// 参数 b: 乘数
// 返回值: 乘积的向量
vector<int> mul(vector<int> a, int b){
    vector<int> res; // 保存乘积的向量
    int temp = 0; // 用于存储进位
    
    // 逐位进行乘法运算
    for(int i = 0; i < a.size() || temp; i++){
        if(i < a.size()) temp = temp + a[i] * b; // 乘数与当前位相乘并加上进位
        res.push_back(temp % 10); // 将个位数字存入结果向量
        temp /= 10; // 更新进位
    }

    // 去除前导0
    while(res.size() > 1 && res.back() == 0) res.pop_back(); // 去除前导0
    reverse(res.begin(), res.end()); // 反转结果向量,得到正确顺序
    
    return res;
}

int main(){
    string A;
    int b;
    cin >> A >> b; // 输入大整数和乘数

    vector<int> a;
    for(int i = A.size() - 1; i >= 0; i--) a.push_back(A[i] - '0'); // 倒着插入,因为乘法要从低位开始运算

    vector<int> result = mul(a, b); // 调用 mul 函数进行乘法运算

    // 输出乘积
    for(int i = 0; i < result.size(); i++) cout << result[i];

    return 0;
}

2.高精度乘以高精度

思路

高精度乘以高精度,就不能用刚刚的方法了。
既然是高精度,那么就只能单个数乘以单个数,比如1x1,3x6,而不能是12x3。

但是得到的结果放在哪里呢?
让我们找一下规律。

在这里插入图片描述
可以发现,a[i]乘以b[j],结果要放在c[i+j]
但是进位怎么办?
很简单,只要先用c数组存储临时结果,最后一步再进位就可以啦

下面代码的temp数组就相当于这里的C数组

代码

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

// 定义一个函数 mul,用于实现大整数乘法
// 参数 A: 第一个大整数的向量形式
// 参数 B: 第二个大整数的向量形式
// 返回值: 乘积的向量
vector<int> mul(vector<int> A, vector<int> B){
    vector<int> temp(A.size() + B.size() + 8, 0); // 临时向量存储乘积结果,预留足够的空间
    for(int i = 0; i < A.size(); i++){
        for(int j = 0; j < B.size(); j++){
            temp[i + j] += A[i] * B[j]; // 计算乘积并累加到正确的位置
        }
    }
    
    //temp数组进位
    int t = 0;
    for(int i = 0; i < temp.size(); i++){
        t += temp[i];
        temp[i] = t % 10; // 取个位作为当前位置的值
        t /= 10; // 更新进位
    }
    
    // 去除前导0
    while(temp.size() > 1 && temp.back() == 0) temp.pop_back(); // 去除前导0
    
    return temp;
}

int main(){
    string a, b;
    cin >> a >> b; // 输入两个大整数

    vector<int> A, B;
    int i;
    for(i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0'); // 将第一个大整数转换为向量形式存储
    for(i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0'); // 将第二个大整数转换为向量形式存储

    auto C = mul(A, B); // 调用 mul 函数进行乘法运算

    // 输出乘积
    for(int i = C.size() - 1; i >= 0; i--) cout << C[i];

    return 0;
}

四、高精度除法

1.高精度除以低精度

思路

假设我们要手算除法,那么接下来应该列一个竖式。

以23456除以12为例,及A=23456,b=12

以下为手算过程,标识符对应第2部分的代码:

(1)首先,用23456的第一个数2除以12,得0,余数为2。
那么这个余数就要乘以10后,加在下一步的计算中
r = r*10 + A [ 1 ] 即 r = 2x10 + 3 = 23

(2)接着,用r=23除以b,得1,余数为11
下一步11要乘以10,加上A[2]=4,得114
……

在这里插入图片描述

由于时间原因 (我懒) ,只写了前三步,后面类似。

注意:最后要去除前导0,所以先将vector翻转,pop_back出最后的0,再翻转回来。

代码

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

// 定义一个函数 div,用于实现大整数除法
// 参数 a: 存储被除数的向量
// 参数 b: 除数
// 参数 r: 余数,通过引用传递以在函数外部访问
// 返回值: 商的向量
vector<int> div(vector<int> a, int b, int& r){
    vector<int> temp;
    for(int i=0; i<a.size(); i++){
        r = a[i] + r * 10; // 将上一次计算的余数乘以10再加上当前位的数字
        temp.push_back(r / b); // 计算商并存入临时向量
        r %= b; // 计算新的余数
    }
    
    // 去除前导0
    reverse(temp.begin(), temp.end()); // 反转临时向量
    while(temp.size() > 1 && temp.back() == 0) temp.pop_back(); // 去除前导0
    reverse(temp.begin(), temp.end()); // 恢复顺序
    
    return temp;
}

int main(){
    string A;
    int b;
    cin >> A >> b; // 输入被除数和除数
    
    vector<int> a;
    for(int i=0; i<A.size(); i++) a.push_back(A[i]-'0'); // 将被除数转换为向量形式存储
    
    int r = 0; // 余数
    auto result = div(a, b, r); // 调用 div 函数进行除法运算
    
    // 输出商
    for(int i=0; i<result.size(); i++) cout << result[i];
    // 输出余数
    cout << endl << r;
    
    return 0;
}

2.高精度除以高精度

先睡个午觉,待会更
zzz~

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云霄星乖乖的果冻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值