0
点赞
收藏
分享

微信扫一扫

高精度算法

程序猿不脱发2 2022-01-26 阅读 52
算法c++

注:

1.截图与代码来自acwing

2.仅作为本人的学习笔记使用

3.有理解不对的地方欢迎大佬指出orz

1.用途:

让10的100次方等大数参与程序运行(long long表示的范围只有10的18次方数量级)

2.存大数怎么实现?

用数组存,把每位拆开放数组里,第0位存个位,倒着存

一、加法

1.运算:模拟人工加法(竖式)

每次运算是相当于三个数相加:A,B,t(进位数)

2.过程

①存储

②运算

ps:

#include<vector>;

a.push_back(5); //在a的最后一个向量后插入一个元素,其值为5

a.size(); //返回a中元素的个数;

3.代码

#include <iostream>

#include <vector>

using namespace std;

vector<int> add(vector<int> &A, vector<int> &B)//引用传参提高效率,要不然电脑还会把整个数组复制一遍

{

    if (A.size() < B.size()) return add(B, A);//如果b长的话,把这两个数反过来,重新调用这个函数

    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一并加在下一位上

        t /= 10;

    }

    if (t) C.push_back(t);//这里是判断最后一位要不要进位

    return C;

}

int main()

{

    string a, b;

    vector<int> A, B;

    cin >> a >> b;//a"1,2,3,4,5,6"

    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');//A[6,5,4,3,2,1]

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

    cout << endl;

    return 0;

}

二、减法

1.每个C都是A-B-t(t是看看上一次运算有没有借位)

2.如果A>=B的话,那就正常,如果A<B的话,算B-A然后加个负号

3.代码

#include <iostream>

#include <vector>

using namespace std;

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 -- )//如果这两个位数相等的话,从A的最后一位开始比,也就是从最高位开始比

        if (A[i] != B[i])

            return A[i] > B[i];//在第i位:Areturn1Breturn0

    return true;//如果二者相等则会走到这一步,return 1

}

vector<int> sub(vector<int> &A, vector<int> &B)

{

    vector<int> C;

    for (int i = 0, t = 0; i < A.size(); i ++ )

    {

        t = A[i] - t;//如果上次计算有借位,则t1

        if (i < B.size()) t -= B[i];//如果B还有的话,减去B(达成A-B

        C.push_back((t + 10) % 10);//现在的tA-进位-B,比如4-1-2模出来是(1+10)%10=1,如果是4-1-5(-2+10)%10=8(就是不管是否进位,先把这个10默认加上,对本来不需要进位的情况不会产生什么影响)

        if (t < 0) t = 1;//在这里判断是不是触发借位条件了(A-进位-B是负数)

        else t = 0;

    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();//除掉前导0,只要不是只有一位,并且C数组最后是0,那就删掉最后的数组元素

    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');

//两个for循环,不是一个

    vector<int> C;

    if (cmp(A, B)) C = sub(A, B);

    else {C = sub(B, A), cout << '-'; }

    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];

    cout << endl;

    return 0;

}

三、乘法

#include <iostream>

#include <vector>

using namespace std;

vector<int> mul(vector<int> &A, int b)

{

    vector<int> C;

    int t = 0;

    for (int i = 0; i < A.size() || t; i ++ )//A还有或者t还有都会让循环进行

    {

        if (i < A.size()) t += A[i] * b;//A还有就加

        C.push_back(t % 10);//t的最后一位存C

        t /= 10;//剩给下一个数的时候少一位

    }

    while (C.size() > 1 && C.back() == 0) C.pop_back(); //个位乘出来是3,但后面t落到C里是0,那就C倒置输出就会出现03,为了避免,返回C前先去掉前导0(我左思右想没想到这样的例子,然后看帖子有人说是避免b=0)

 

    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');

    auto C = mul(A, b);

    for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);

    return 0;

}

双精版

#include<bits/stdc++.h>

using namespace std;

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;

}

vector<int>mul(vector<int>&A,int b){

    vector<int>C;

    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;

    }

    while(C.size()>1&&C.back()==0)C.pop_back();

    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');

    vector<int>C;

    C.push_back(0);

     for(int i=A.size()-1;i>=0;i--){//A数组或B数组的高位开始单精乘

        C=add(C,mul(B,A[i]));

          C.insert(C.begin(),0);

        C[0]=0;

    for(int i=C.size()-1;i>=1;i--){

        cout<<C[i];

    }

    return 0;

}

四、除法

和之前的不同,这个得从高位开始处理,所以函数里的for循环从A.size()-1往0执行

r是余数,r每次留下来都*10再加上下一个掉下来的A,有点像倒置

代码:

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

vector<int> div(vector<int> &A, int b, int &r)//这个r就是单纯为了得到余数的

{

    vector<int> C;

    r = 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());//咱是从高位处理的,为了和加减乘一致,再倒回去

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

    return C;

}

int main()

{

    string a;

    vector<int> A;

    int B;

    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;

}

举报

相关推荐

高精度算法模板

算法:高精度(大数)

C++算法(高精度算法)

算法提高 高精度乘法

【基础算法】高精度加法

算法之高精度(三)

算法之高精度(四)

0 条评论