C++实现高精度算法

目录

高精度加法

高精度减法

高精度乘法

高精度除法


高精度算法存在的理由主要就是因为数字太大,用int或者long不足以承受,所以可以通过使用数组或者vector来实现高精度的加减乘除算法。这个算法是需要面对题目来讲解的,所以后面讲解四个题目分别是高精度加减乘除。

高精度加法

给定两个正整数(不含前导 0),计算它们的和。

输入格式

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

输出格式

共一行,包含所求的和。

数据范围

1≤整数长度≤100000

输入样例:

12 23

输出样例:

35

实现高精度加法的基本思路是这样的:

  • 创建两个vector,分别用来存储输入进来的数

  • 从低位到高位加,注意进位,最后输出

但是要实现这个思路需要有一些注意点,比如说数据太大,不能用int从控制台把数据输入进来,所以需要使用string来保存输入的数据,用vector来保存最终的结果,但是如果要从小到大依次加,可能会发生进一位,所以需要让从控制台输入的数据按逆序保存在vector中,然后在进行加法。

下面是具体的代码:

#include<iostream>
#include<vector>
using namespace std;
​
const int N = 1e6 + 10;
​
vector<int> add(vector<int> &A, vector<int> &B){
    vector<int> C;
    
    int t = 0; // 用来保存是否进位
    for(int i = 0; i < A.size() || i < B.size(); i++){
        if(i < A.size()) t += A[i]; // 如果此时i的下标还没有超出A的范围就加
        if(i < B.size()) t += B[i]; // 如果此时i的下标还没有超出B的范围就加
        C.push_back(t % 10); // 余10是因为相加的结果可能会大于10
        t /= 10; // 如果t大于10说明需要进一,所以结果就是下一次加会把这个进一也算上
    }
    
    if(t) C.push_back(1); // 此时如果t为0说明没有进位,如果t为1说明两个数相加后需要位数比二者都大
    return C;
}
​
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');
    
    auto C = add(A, B);
    
    for(int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]); // 输出结果
    return 0;
}

高精度减法

题目:

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

输入格式

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

输出格式

共一行,包含所求的差。

数据范围

1≤整数长度≤105

输入样例:

32 11

输出样例:

21

高精度减法也跟加法相差不多,只是它比加法多了判断两个数大小的操作。

基本的实现步骤:

  1. 从控制台读取需要相加的两个数,用vector保存这个数的倒序

  2. 判断两个数谁大,用大的数减去小的数

  3. 如果是小的数减大的数,在输出结果前需要先输出 “ - ”

注意点:

  1. 如果低位数借一需要让高位减一

  2. 最终得到的vector可能高位会有0,此时需要除去这些0,比如说下面这种情况

 

代码如下:

#include<iostream>
#include<vector>
​
using namespace std;
​
// 判断两个数的大小
bool cmp(vector<int> &A, vector<int> B){
  if(A.size() != B.size()){ // 如果两个vector的大小不一样,直接比较二者的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){
    
    int t = 0; // 用于保存是否借位
    vector<int> C; // 用于保存最终的结果
    for(int i = 0; i < A.size(); i++){
      t = A[i] - t; // 如果借位了,先让A[i]减去借的
      if(i < B.size()) t -= B[i]; // 如果i此时还没有到B的末尾,就继续减
      C.push_back((t + 10) % 10); // 如果二者相减结果小于0,需要借位,所以通过这种方式可以获取结果。如果大于0,按照这样的做法也不会有差。直接将两种可能结合
      if(t < 0) t = 1; // 如果t小于0,说明借位了,把t设置成1
      else t = 0; // 否则,说明不需要借位,设置为0
    }
    // 如果高位有0,需要除去
    while(C.size() > 1 && C.back() == 0) // 这个判断保证了必须起码有一位,因为如果两个数相同,必须输出 0
      C.pop_back();
    
    return C;
}
​
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');
​
    if(cmp(A, B)){ // 如果a > b,此时用A减去B
      auto C = sub(A, B);
      
      for(int i = C.size() - 1; i >= 0; i--)
        cout << C[i];
    }else{ // 否则,用B减去A
      auto C = sub(B, A);
      cout << "-"; // 在输出结果前需要先输出 -
      for(int i = C.size() - 1; i >= 0; i--)
        cout << C[i];
    }
   
    return 0;
}

高精度乘法

题目:

给定两个非负整数(不含前导 0) A 和 B,请你计算 A×B 的值。

输入格式

共两行,第一行包含整数 A,第二行包含整数 B。

输出格式

共一行,包含 A×B的值。

数据范围

1≤A的长度≤100000, 0≤B≤10000

输入样例:

2 3

输出样例:

6

注意点:输入的两个数一个数是很大的**,而第二个数是可以用long来存储的

实现步骤:

  1. 让A从个位到最高位乘以B

  2. 创建变量t,用来保存计算的结果,每当用A的一位乘以B后,就将这个数加到t上,然后把t%10在存到新的vector中

  3. 循环结束的条件是用A的每一位都乘以B了并且t的值为0

代码实现:

#include<iostream>
#include<vector>
using namespace std;
​
vector<int> mul(vector<int> &A, int b){
    int t = 0; // 用来保存进行乘法的结果
    vector<int> C; // 用来保存最终的输出
    for(int i = 0; i < A.size() || t; i++){ // 如果A中的所有数还没有都用到或者t不为0,就继续循环
        if(i < A.size()) t += A[i] * b; // 如果此时还没有用A的最高位乘以b,就把乘法的结果加到t上
        C.push_back(t % 10); // 把t%10的结果保存到C中
        t /= 10; // 除去t的最后一位
    }
    // 把多余的0除去
    while(C.size() > 1 && C.back() == 0){
        C.pop_back();
    }
    return C;
}
​
int main(){
    
    string a; // 用来存储大的数
    int b; // 存储较小的那个数
    cin >> a >> b;
    
    vector<int> A; // 用来保存a中的数据
    for(int i = a.size() - 1; i >= 0; i--){
        A.push_back(a[i] - '0'); // 使a倒序并把字符转换成整型
    }
    
    vector<int> C = mul(A, b); // 获取结果
    for(int i = C.size() - 1; i >= 0; i--){
        cout << C[i]; // 输出结果
    }
    
    return 0;
}

高精度除法

题目:

给定两个非负整数(不含前导0) A,B,请你计算 A/B 的商和余数。

输入格式

共两行,第一行包含整数 A,第二行包含整数 B。

输出格式

共两行,第一行输出所求的商,第二行输出所求余数。

数据范围

1≤A的长度≤100000, 1≤B≤10000, B 一定不为 0

输入样例:

7 2

输出样例:

3 1

步骤:

  1. 从高位到低 位除以除数,直到A中的所有数都用到了

  2. 将除后的结果保存到vector中,取得的余数保存到r中

  3. 具体的还得落实到代码中,代码中详细说明了这些步骤的原因以及作用

代码实现:

 

 

下面这幅图是对除法循环中进行的步骤的解释:

#include<iostream>
#include<vector>
#include<algorithm>
​
using namespace std;
​
vector<int> div(vector<int> &A, int b, int &r){
    vector<int> C; // 保存计算的结果
    r = 0; // 将余数重置为0
    for(int i = A.size() - 1; i >= 0; i--){
        r = r * 10 + A[i]; // 计算本次要被除的数
        C.push_back(r / b); // 将本次除法的结果保存
        r %= b; // 获取余数
    }
    reverse(C.begin(), C.end()); // 计算的结果是按照从大到小的顺序保存到C中的,所以需要将它倒序
    while(C.size() > 1 && C.back() == 0){ // 除去多余的0
        C.pop_back();
    }
    return C;
}
​
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'); // 将字符装换成整型
    }
    
    int r; // 用于保存余数
    auto C = div(A, b, r); // 计算结果
​
    for(int i = C.size() - 1; i >= 0; i--){ // 输出结果
        cout << C[i]; 
    }
    cout << endl << r << endl;
​
    return 0;
}

以上就是本次高精度算法的全部,如果有错误欢迎指出,或者有什么不足欢迎来讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值