【AcWing_算法基础课】高精度:加减乘除

高精度加法:

原题链接: AcWing 791.高精度加法

给定两个正整数,计算它们的和。

输入格式
共两行,每行包含一个整数。

输出格式
共一行,包含所求的和。

数据范围
1≤整数长度≤100000
输入样例:

12
23

输出样例:

35

思路:

大整数肯定不能用int来存,考虑用数组
并且存储用低位到高位来存(为了方便低位对齐,方便进位)
例如数字123456789,存到数组中就是[9, 8, 7, 6, 5, 4, 3, 2, 1]

C++代码:

#include 
#include 
using namespace std;

vector<int> A, B;

// 高精度加法模板
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];
        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;
    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;
}


高精度减法:

原题链接: AcWing 792.高精度减法

给定两个正整数,计算它们的差,计算结果可能为负数。

输入格式
共两行,每行包含一个整数。

输出格式
共一行,包含所求的差。

数据范围
1≤整数长度≤105
输入样例:

32
11

输出样例:

21

思路:

和高精加类似,也是倒着存到数组(为了低位对齐)返回结果
区别在于:

  • 减法需要考虑两个数的大小,做到 被减数大于等于减数 ,同时别忘了负号
  • 借位问题
  • 前导0的问题

C++代码:

#include 
#include 
using namespace std;

vector<int> A, B;

// 判断x是否大于等于y
bool cmp(vector<int> x, vector<int> y){
    if(x.size() != y.size()) 
        return x.size() > y.size();
        
    for(int i = x.size() - 1; i >= 0; i-- ){
        if(x[i] != y[i])
            return x[i] > y[i];
    }
    return true;
}

// 高精度减法模板
vector<int> sub(vector<int> A, vector<int> B){
    vector<int> C;
    
    for(int i = 0, t = 0; i < A.size(); i++ ){
        // t是这一位的结果
        t = A[i] - t;
        if(i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        
        // t小于0时说明有借位, 变为1留给下一位减
        if(t < 0) t = 1;
        else t = 0;
    }
    // 减法需要去掉前导0 此时前导0在数组最后面
    while(C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main(){
    string 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');
    
    // cout << cmp(A, B) << endl;
    if(cmp(A, B)){
        auto C = sub(A, B);
        for(int i = C.size() - 1; i >= 0; i-- ) cout << C[i];
    }
    else{
        auto C = sub(B, A);
        // 要加个负号
        cout << '-';
        for(int i = C.size() - 1; i >= 0; i-- ) cout << C[i];
    }
        
    return 0;
}

高精度乘法:

原题链接: AcWing 793.高精度乘法

给定两个正整数 A 和 B,请你计算 A×B 的值。

输入格式
共两行,第一行包含整数 A,第二行包含整数 B。

输出格式
共一行,包含 A×B 的值。

数据范围
1≤A的长度≤100000,
0≤B≤10000
输入样例:

2
3

输出样例:

6

思路:

题目中给出的b比较小,因此可以直接当一个数来进行运算
思路和加法差不多,也是用一个数组倒着存a,然后一位一位运算
注意:

  • 进位处理
  • 先导0处理

C++代码:

#include 
#include 
using namespace std;

vector<int> A;

vector<int> mul(vector<int> A, int b){
    vector<int> C;
    
    // t当前位的结果 进位
    int t = 0;
    for(int i = 0; i < A.size() || t; i ++ ){
        if(i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    
    // 去掉先导0
    while(C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

int main(){
    string a;
    int b;
    cin >> a >> b;
    
    for(int i = a.size() - 1; i >= 0; i-- ) A.push_back(a[i] - '0');
    
    auto C = mul(A, b);
    for(int i = C.size() - 1; i >= 0; i-- ) cout << C[i];
    
    return 0;
}

高精度除法:

原题链接:AcWing.794 高精度除法

给定两个非负整数 A,B,请你计算 A/B 的商和余数。

输入格式
共两行,第一行包含整数 A,第二行包含整数 B。

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

数据范围
1≤A的长度≤100000,
1≤B≤10000,
B 一定不为 0
输入样例:

7
2

输出样例:

3
1

思路:

输出输出和乘法一样,而且也是一个相对大的数除一个相对小的数
主要的区别在于:

  • 加减乘都是从低位算起,乘法是从高位算起
  • 单独除法正着存比较好,为了和加减乘统一,才采用倒着存

C++代码:

#include 
#include 
#include 
using namespace std;

vector<int> A;
int b;

// 计算a和b 余数是r
vector<int> div(vector<int> &A, int b, int &r){
    vector<int> C;
    r = 0;
    
    // 除法从最高位来除
    for(int i = A.size() - 1; i >= 0; i -- ){
        // 前一位留下的余数乘10再加上这一位
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    // 为了和加减乘统一 也倒着存答案
    reverse(C.begin(), C.end());
    
    // 去掉先导0
    while(C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

int main(){
    string a;
    cin >> a >> b;
    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;
}

你可能感兴趣的:(算法学习,高精度)