高精度

这东西暂且归为数据结构吧

巨难写的东西,恶心死个人。(但用还是要用的
说实话不常用,但是该用的时候还真没有能替代的。

正常C++,int类型最大长度为9位,longlong约为18位,就算是__int128也不过30多位
而有的时候,我们需要用到几百上千位,这时候就得用到高精度了。
它的中心思想是用字符串存下数,利用字符串模拟加减乘数的运算
但时代在进步,现在好像都用vector来存储大整数。

注意,高精度有一种缩短时间和空间的方法,叫压位,正常我们每个int只存1位数,但这样太浪费了,都知道int最大是9位,那么我们就让int存9位,这样就缩小了时间和空间。一般压8位而不压9位,为了防止以外爆炸,对于高精乘低精则更低

读入

一般利用字符串读入,然后用vector存起来。
注意一般是逆序转存,因为我们操作的时候是从最低位开始的

非压位

void read(string &s1, vector<int> &A)
{
    for (int i = s1.size() - 1; i >= 0; i -- ) A.push_back(s1[i] - '0');
}

压位版

这玩意看看代码应该就明白了。
注意一点j == 9那里压多少位写多大的数

void read(string &s1, vector<int> &A)
{
    for (int i = s1.size() - 1, t = 1, s = 0, j = 0; i >= 0; i -- )
    {
        s += (s1[i] - '0') * t;
        j ++ , t *= 10;
        if (j == 9 || i == 0) 
        {
            A.push_back(s);
            s = j = 0;
            t = 1;
        }
    }
}

输出

注意逆序输入就要逆序输出

非压位

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

压位

压位版因为C的首位不确定长度所以要先输出来,
而在后面可能会遇到因取模而小于压位位数的情况,所以我们要用printf固定输出,空缺补0

cout << C.back();
for (int i = C.size() - 2; i >= 0; i -- ) printf("%09d", C.[i]);

高精加

高精加有两种,一种为高精加高精,一种为高精加低精,但是高精加低精更少用,所以这里只写高精乘高精。

注意不能存负数,鬼才想处理正负号

非压位和压位几乎没有区别,实质上都是压位版,只不过压1位就是不压而已。

非压位

vector<int> M_add(vector<int> A, vector<int> B)
{
    if (A.size() < B.size()) return M_add(B, A);
    
    vector<int> C;
    int t = 0, len = A.size();
    for (int i = 0; i < len; 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;
}

压位

int base = 1000000000; // 压位数组
vector<int> M_add(vector<int> A, vector<int> B)
{
    if (A.size() < B.size()) return M_add(B, A);
    
    vector<int> C;
    int t = 0, len = A.size();
    for (int i = 0; i < len; i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % base);
        t /= base;
    }

    if (t) C.push_back(t);
    return C;
}

高精减

和高精加有所不同,注意不够减了借位。最多借base位

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> C;
    int t = 0, len = A.size();
    for (int i = 0; i < len; i ++ )
    {
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0) t = 1; // 减下一位的
        else t = 0;
    }
    
    while (C.back() == 0 && C.size() > 1) C.pop_back();
    return C;
}

int main()
{
    cin >> s1 >> s2;
    for (int i = s1.size() - 1; i >= 0; i -- ) A.push_back(s1[i] - '0');
    for (int i = s2.size() - 1; i >= 0; i -- ) B.push_back(s2[i] - '0');
    
    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];
    
    return 0;
}

高精乘

高精乘高精不常用,实际上跟着思路也能写出来,但速度慢,而且难调
兴许哪天脑子用了写个高精除高精

高精乘低精

vector<int> M_mul(vector<int> A, int b)
{
    vector<int> C;
    int t = 0, len = A.size();
    for (int i = 0; i < len || t; i ++ ) // 一定要把t搞干净
    {
        if (i < len) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    
    while (C.back() == 0 && C.size() > 1) C.pop_back();
    return C;
}

高精除

高精除低精简单,高精除高精困难,这里说个思路,高精除高精,化除为减是一个办法

vector<int> divi(vector<int> &A, int b, int &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()); // C push进去的先是高位后是低位,为了输出的一致所以要逆序
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    
    return C;
}

好久以前的高精除高精

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

const int N=200010;

int a[N],b[N],n,m;
long long sum;
char s1[N],s2[N];

bool bol()
{
    if (n!=m) return n>m;
    for (int i=1;i<=n;i++) 
        if(a[i]!=b[i]) return a[i]>b[i];
    return true;
}

void cut()
{
    for (int i=1;i<=n||i<=m;i++)
    {
        a[i]-=b[i];
        if (a[i]<0)
        {
            a[i+1]--;
            a[i]+=10;
        }
    }
    while(!a[n]&&n>1) n--;
    sum++;
}
int main()
{
    cin>>s1>>s2;
    //n=s1.size();
   // m=s2.size();
    n=strlen(s1);
    m=strlen(s2);
    for (int i=1;i<=n;i++) a[i]=s1[n-i]-'0';
    for (int i=1;i<=m;i++) b[i]=s2[m-i]-'0';
    while (bol())
    {
        cut();
    }
    cout<<sum<<endl;
    while (n) cout<<a[n--];
    return 0;
}
posted @ 2025-12-30 20:29  blind5883  阅读(6)  评论(0)    收藏  举报