高精度HighAccuracy【算法模板笔记】

/*HighAccuracy_oiwiki.cpp*/
#include <cstdio>
#include <cstring>

static const int LEN = 10005;// 定义静态的长度变量LEN

int a[LEN], b[LEN], c[LEN], d[LEN];// 定义高精度数组

void clear(int a[]) {// 高精度数组清零操作
    for (int i = 0; i < LEN; ++i) a[i] = 0;
}


bool cmp(int a[], int b[])// 高精度比较函数
{
    for (int i = LEN - 1; i >= 0; --i){
        if (a[i] > b[i]) return true;
        if (a[i] < b[i]) return false;
    }
    return true;
}

void read(int a[]) {// 输入高精度数
    static char s[LEN + 1];
    scanf("%s", s);

    clear(a);

    int len = strlen(s);
    for (int i = 0; i < len; ++i) a[len - i - 1] = s[i] - '0';//实现了倒序,即个十百千万0000···
}

void print(int a[]) {// 输出高精度数
    int i;
    for (i = LEN - 1; i >= 1; --i)//去掉后面的零,即 个十百千万0000··· 变成 个十百千万
        if (a[i] != 0) break;
    for (; i >= 0; --i) putchar(a[i] + '0');
    putchar('\n');
}

void add(int a[], int b[], int c[]) {// 高精度加法(高精度加高精度)
    clear(c);

    for (int i = 0; i < LEN - 1; ++i) {
        c[i] += a[i] + b[i];
        if (c[i] >= 10) {
            c[i + 1] += 1;
            c[i] -= 10;
        }
    }
}

void sub(int a[], int b[], int c[]) {// 高精度减法(高精度减高精度)
    clear(c);

    for (int i = 0; i < LEN - 1; ++i) {
        c[i] += a[i] - b[i];
        if (c[i] < 0) {
            c[i + 1] -= 1;
            c[i] += 10;
        }
    }
}

void mul(int a[], int b[], int c[]) {// 高精度乘法(高精度乘以高精度)
    clear(c);

    for (int i = 0; i < LEN - 1; ++i) {
        for (int j = 0; j <= i; ++j) c[i] += a[j] * b[i - j];

        if (c[i] >= 10) {
            c[i + 1] += c[i] / 10;
            c[i] %= 10;
        }
    }
}

inline bool greater_eq(int a[], int b[], int last_dg, int len) {// 判断大小数组(具体原理请参照OIwiki)
  if (a[last_dg + len] != 0) return true;
  for (int i = len - 1; i >= 0; --i) {
    if (a[last_dg + i] > b[i]) return true;
    if (a[last_dg + i] < b[i]) return false;
  }
  return true;
}

void div(int a[], int b[], int c[], int d[]) {// 高精度除法(高精度除以高精度)
  clear(c);
  clear(d);

  int la, lb;
  for (la = LEN - 1; la > 0; --la)
    if (a[la - 1] != 0) break;
  for (lb = LEN - 1; lb > 0; --lb)
    if (b[lb - 1] != 0) break;
  if (lb == 0) {
    puts("> <");
    return;
  }

  for (int i = 0; i < la; ++i) d[i] = a[i];
  for (int i = la - lb; i >= 0; --i) {
    while (greater_eq(d, b, i, lb)) {
      for (int j = 0; j < lb; ++j) {
        d[i + j] -= b[j];
        if (d[i + j] < 0) {
          d[i + j + 1] -= 1;
          d[i + j] += 10;
        }
      }
      c[i] += 1;
    }
  }
}

int main() {
    freopen("luogu_in.txt","r",stdin);  // 文件输入  
    freopen("luogu_out.txt","w",stdout);// 文件输出  
    read(a);

    char op[4];
    scanf("%s", op);

    read(b);

    switch (op[0]) {
        case '+':
            add(a, b, c);
            print(c);
            break;
        case '-':
            if(cmp(a, b)) sub(a, b, c);
            else{
               printf("-");
              sub(b, a, c);
            }
            print(c);
            break;
        case '*':
            mul(a, b, c);
            print(c);
            break;
        case '/':
            div(a, b, c, d);
            print(c);
            print(d);
            break;
        default:
            puts("> <");
    }

    return 0;
}
/*HighAccuracy_acwing.cpp*/
#include<bits/stdc++.h>
using namespace std;


bool sub_plus(vector<int> &a, vector<int> &b){//0表示负数,1表示正数
    if(a.size()<b.size()) return 0;
    if(a.size()==b.size()){
        for(int i = 0; i<a.size(); i++){
            if(a[i]<b[i]){
                return 0;
            }
        }
    }
    return 1;
}

vector<int> add(vector<int> &A, vector<int> &B){  //正序输入两个vector类型的“数”
    if (A.size() < B.size()) return add(B, A);  //使得A数组是最大的
    //如果未反转,在if下面加reverse,不能在if上面加reverse,否者二次反转,等于没有反转

    reverse(A.begin(),A.end());  //反转数组,变成个十百千万···
    reverse(B.begin(),B.end());
    vector<int> c;  //初始化答案数组
    int t = 0;
    for (int i = 0; i < A.size(); i ++ ){
        t += A[i];
        if (i < B.size()) t += B[i];  //如果B还有数字
        c.push_back(t % 10);
        t /= 10;
    }
    if (t) c.push_back(t);//最后一次加法可能还有进位的数,把最高位补上
    while (c.size() > 1 && c.back() == 0) c.pop_back();//处理前导零
    reverse(c.begin(), c.end());
    return c;
}

// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> &A, vector<int> &B){
    reverse(A.begin(),A.end());  //反转数组,变成个十百千万···
    reverse(B.begin(),B.end());
    vector<int> C;
    for (int i = 0, t = 0; i < A.size(); i++ ){
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);//无论如何,先向高位借1
        if (t < 0) t = 1;//t是负数,说明是真的借1了
        else t = 0;//t是非负数,说明不用借1
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    reverse(C.begin(), C.end());
    return C;
}

//不清楚c数组开多大
vector<int> multwo(vector<int> &a, vector<int> &b){
    if(a.size()<b.size()) return multwo(b,a);
    vector<int> c(1000001,0);  //初始化答案数组(不知道开多大)
    reverse(a.begin(), a.end());  //反转数组,变成个十百千万···
    reverse(b.begin(), b.end());
    int t = 0;
    for(int i = 0; i<b.size(); i++){  //b数组数少,是外循环
        for(int j = 0; j<a.size() || t; j++){  //a数组数多,是内循环
            if(j<a.size()) t += a[j]*b[i];
            c[j+i] += t % 10;
            t /= 10;
        }
    }
    //处理c数组的进位
    for(int i = 0; i<a.size()*b.size(); i++){  //无论数字如何大,数位也不会大于两个乘数的和
        if(c[i]>9){
            c[i+1]+=c[i]/10;
	        c[i]%=10;
        }
    }
    while (c.size() > 1 && c.back() == 0) c.pop_back();  //末尾可能是0,都要去掉(我感觉是多余的,不可能有这种情况)(难道是处理b==0?)
    reverse(c.begin(), c.end());
    return c;
}

/*除法*/
// A / b = C ... r, A >= 0, b > 0
vector<int> div(vector<int> &A, int b, int &r){
    reverse(A.begin(), A.end());
    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();
    reverse(C.begin(), C.end());//高位在左,低位在右
    return C;
}

int main(){
    string in; getline(cin,in);
    vector<int> a;
    vector<int> b;
    vector<int> c;
    char f;
    int i;

    for(i = 0; i<in.size(); i++){
        if(in[i]!=' ') a.push_back(in[i]-'0');
        else break;
    }

    i++;
    f = in[i];
    i+=2;

    for(i; i<in.size(); i++) b.push_back(in[i]-'0');

    switch (f) {
        case '+':
            c = add(a,b);
            break;
        case '-':
            //增加负号
            if(!sub_plus(a,b)){
                printf("-");
                c = sub(b,a);
            }
            else c = sub(a,b);
            break;
        case '*':
            c = multwo(a,b);
            break;
        case '/':
            int bb = b[0]; int d;
            c = div(a,bb,d);
            break;
        // default:
        //     puts("> <");
    }
    for(int i = 0; i<c.size(); i++) printf("%d", c[i]);

    return 0;
}

/*

*/
/*HighAccuracy_additional.cpp*/
#include<bits/stdc++.h>
using namespace std;


// C = A + B, A >= 0, B >= 0
//这里不加&,就可以避免改变了原来的a,b数组,使得a,b数组可以重复利用
vector<int> add(vector<int> A, vector<int> B){  //正序输入两个vector类型的“数”
    if (A.size() < B.size()) return add(B, A);  //使得A数组是最大的
    //如果未反转,在if下面加reverse,不能在if上面加reverse,否者二次反转,等于没有反转
    
    reverse(A.begin(),A.end());  //反转数组,变成个十百千万···
    reverse(B.begin(),B.end());
    vector<int> c;  //初始化答案数组
    int t = 0;
    for (int i = 0; i < A.size(); i ++ ){
        t += A[i];
        if (i < B.size()) t += B[i];  //如果B还有数字
        c.push_back(t % 10);
        t /= 10;
    }
    if (t) c.push_back(t);//最后一次加法可能还有进位的数,把最高位补上
    reverse(c.begin(), c.end());
    return c;
}

string add(string a, string b){
    if(a.size()<b.size()) return add(b,a);
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    int t = 0;
    string c;
    for(int i = 0; i<a.size(); i++){
        t += a[i] - '0';
        if(i<b.size()) t+=b[i] - '0';
        c.push_back(t%10 + '0');
        t /= 10;
    }
    if(t) c.push_back(t + '0');
    reverse(c.begin(), c.end());
    return c;
}

// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> A, vector<int> B){
    reverse(A.begin(),A.end());  //反转数组,变成个十百千万···
    reverse(B.begin(),B.end());
    vector<int> C;
    for (int i = 0, t = 0; i < A.size(); i++ ){
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);//无论如何,先向高位借1
        if (t < 0) t = 1;//t是负数,说明是真的借1了
        else t = 0;//t是非负数,说明不用借1
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    reverse(C.begin(), C.end());
    return C;
}

/*高精度乘低精度 —— 模板题*/
// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> A, int b){  //输入正序的高精度A和低精度b
    vector<int> C;  //初始化答案数组
    reverse(A.begin(),A.end());  //反转数组,变成个十百千万···
    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 /= 10;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();  //末尾可能是0,都要去掉(我感觉是多余的,不可能有这种情况)(难道是处理b==0?)
    reverse(C.begin(),C.end());  //反转数组,恢复正序
    return C;
}

string mul(string a, int b){
    reverse(a.begin(), a.end());
    string c;
    int t = 0;
    for(int i = 0; i<a.size() || t; i++){
        if(i<a.size()) t += (a[i] - '0') * b;
        c.push_back(t%10 + '0');
        t /= 10;
    }
    while(c.size()>1 && c.back() == 0)c.pop_back();
    reverse(c.begin(), c.end());
    return c;
}

//不清楚c数组开多大
vector<int> multwo(vector<int> a, vector<int> b){
    if(a.size()<b.size()) return multwo(b,a);
    vector<int> c(10001,0);  //初始化答案数组(不知道开多大)
    reverse(a.begin(), a.end());  //反转数组,变成个十百千万···
    reverse(b.begin(), b.end());
    int t = 0;
    for(int i = 0; i<b.size(); i++){  //b数组数少,是外循环
        for(int j = 0; j<a.size() || t; j++){  //a数组数多,是内循环
            if(j<a.size()) t += a[j]*b[i];
            c[j+i] += t % 10;
            t /= 10;
        }
    }
    //处理c数组的进位
    for(int i = 0; i<a.size()*b.size(); i++){  //无论数字如何大,数位也不会大于两个乘数的和
        if(c[i]>9){
            c[i+1]+=c[i]/10;
	        c[i]%=10;
        }
    }
    while (c.size() > 1 && c.back() == 0) c.pop_back();  //末尾可能是0,都要去掉(我感觉是多余的,不可能有这种情况)(难道是处理b==0?)
    reverse(c.begin(), c.end());
    return c;
}

/*除法*/
// A / b = C ... r, A >= 0, b > 0
vector<int> div(vector<int> &A, int b, int &r){
    reverse(A.begin(), A.end());
    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();
    reverse(C.begin(), C.end());//高位在左,低位在右
    return C;
}



int main(){
    //加法
    vector<int> addint1 = {1,2,3,4,5,6,7,8,9};
    vector<int> addint2 = {9,8,7,6,5,4,3,2,1,0};
    vector<int> addint3 = add(addint1,addint2);
    for(int i = 0;i<addint3.size(); i++) cout<<addint3[i];
    printf("\n");

    //加法
    string addstr1 = {"123456789"};
    string addstr2 = {"9876543210"};
    string addstr3 = add(addstr1,addstr2);
    cout<< addstr3 <<endl;

    //减法
    vector<int> subint1 = {9,8,7,6,5,4,3,2,1,0};
    vector<int> subint2 = {9,0,7,0,5,0,3,0,1,0};
    vector<int> subint3 = sub(subint1,subint2);
    for(int i = 0;i<subint3.size(); i++) cout<<subint3[i];
    printf("\n");

    //乘法(高精度*低精度)
    vector<int> mulint1 = {9,0,0,8,0,0,7,0,0,6,0,0,5,0,0,4,0,0,3,0,0,2,0,0,1};
    int mulint2 = 9;
    vector<int> mulint3 = mul(mulint1,mulint2);
    for(int i = 0;i<mulint3.size(); i++) cout<<mulint3[i];
    printf("\n");

    //乘法(高精度*低精度)
    string mulstr1 = "9008007006005004003002001";
    int mulstr2 = 9;
    cout<<mul(mulstr1,mulstr2)<<endl;

    //乘法(高精度*高精度)
    vector<int> multwo1 = {1,2,3,4,5,6,7,8,9};
    vector<int> multwo2 = {1,2,3,4,5,6,7,8,9};
    vector<int> multwo3 = multwo(multwo1,multwo2);
    for(int i = 0;i<multwo3.size(); i++) cout<<multwo3[i];
    printf("\n");
    
    //除法(高精度/低精度)
    vector<int> divint1 = {8,1,0,7,2,0,6,3,0,5,4,0,4,5,0,3,6,0,2,7,0,1,8,0,0,9};
    int divint2 = 9;
    int divintr = 0;
    vector<int> divint3 = div(divint1,divint2,divintr);
    for(int i = 0;i<divint3.size(); i++) cout<<divint3[i];
    printf("\n");

    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值