高精度算法

高精度算法

问题引入

给你两个十进制运算数a, b,它们的长度不超过1000。你需要求解 a (op) b 的值(op 为 +, -, *, / 运算中的一种)。
:C++中long long 能表示的最大十进制数为"9223372036854775807"

数据存储

显然longlong也无法存储这个两个运算数了。在平常的实现中,高精度数字利用字符串表示,每一个字符表示数字的一个十进制位。因此可以说,高精度数值计算实际上是一种特别的字符串处理。
在读入字符串时,最高位在字符串首,但是习惯上,我们将最低位置于字符串首即翻转存储字符串。我们这么做的原因是将数位对齐。下面是一个例子: 1234 和 100

4321
0010

我们规定:各位在下标0,十位在下标1 …逆序存储。可以写出下面的存储程序

    void input(string a, string b){
        clear();
        la = a.length(), lb = b.length();
        for(int i = la - 1; i >= 0; i--) A[la - i - 1] = a[i] - '0'; 
        for(int i = lb - 1; i >= 0; i--) B[lb - i - 1] = b[i] - '0'; 
  
    }

加法

我们模拟竖式加法。
竖式加法

从低位开始处理,若当前位C[i] >= 10, 后一位 C[i + 1] += 1, C[i] %= 10。

   void add(){
       int lc = max(la, lb);
       for(int i = 0; i < la; i++){
           C[i] += A[i] + B[i];
           C[i + 1] += C[i]/10;
           C[i] = C[i] % 10;
       }
       erase_pre0(C, lc); //去除前导0
       Print(C, lc);  //输出答案
   }

减法:

类似于加法的实现,模拟竖式减法。需要处理一个细节,若 A >= B,我们可以直接模拟。 若 A < B 我们可以先交换A, B 最后先输出负号,再输出结果即可。需要先实现一个比较大小的函数。

 void sub(){
        if(!(greater_eq(A, B, 0, lb))) {
            cout <<"-";
            swap(A, B);
        }
        int lc = max(la, lb);
        for(int i = 0; i < la; i++){
            C[i] += A[i] - B[i];
            if(C[i] < 0){
                C[i + 1] -= 1;
                C[i] += 10;
            }
        }
        erase_pre0(C, lc);
        Print(C, lc);
    }

乘法

A i A_i Ai 表示A的第i位, B j B_j Bj表示B的第j位。 A i A_i Ai = a × \times × 1 0 i 10^i 10i, B j B_j Bj = b × \times × 1 0 j 10^j 10j A i A_i Ai × \times × B j B_j Bj = a × \times × b × \times × 1 0 i + j 10^{i + j} 10i+j。我们按序处理每一位。

     void mul(){
        int lc = la + lb;
        for(int i = 0; i < la; i++){
            for(int j = 0; j < lb; j++){
                C[i + j] += A[i]*B[j];
                C[i + j + 1] += C[i + j]/10;
                C[i + j] = C[i + j]%10;
            }
        }
        erase_pre0(C, lc);
        Print(C, lc);
    }

除法(高精度除高精度)

终于要完成了!!!
在高精度除法中,我们使用减法来模拟除法的过程,例如45 / 12,我们可以这么看45 - 12 - 12 - 12 = 9,即45/12 = 3 余 9。我们用高精度除法来模拟竖式长除。在这过程中有一个细节,我们需要比较被除数和除数的大小,可以借助上面减法程序中的比较函数。

    void div(){
        int lc = max(la, lb);
        int ld = lc;
        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;
            }
        }
        erase_pre0(C, lc);
        erase_pre0(D, ld);
        Print(C, lc);
        Print(D, ld);
    }

基本高精度算法!完成!

自己写的高精度计算器类

 class calculator{
private:
public:
    int A[N], B[N], C[N], D[N];
    int la, lb;
    void clear(){
        memset(A, 0, sizeof(A));
        memset(B, 0, sizeof(B));
        memset(C, 0, sizeof(C));
        memset(D, 0, sizeof(D));
    }
    calculator(){
        clear();
    }
    void input(string a, string b){
        clear();
        la = a.length(), lb = b.length();
        for(int i = la - 1; i >= 0; i--) A[la - i - 1] = a[i] - '0'; 
        for(int i = lb - 1; i >= 0; i--) B[lb - i - 1] = b[i] - '0'; 
    }
    
    calculator(string a, string b){
        la = a.length(), lb = b.length();
        for(int i = la - 1; i >= 0; i--) A[la - i - 1] = a[i] - '0'; 
        for(int i = lb - 1; i >= 0; i--) B[lb - i - 1] = b[i] - '0'; 
    }
    void Print(int a[], int pos){
        for(int i = pos; i >= 0; i--) cout << a[i];
        cout << endl;
    }
    bool greater_eq(int a[], int b[], int last_dg, int len){
        if(a[last_dg + len] != 0) return 1;
        for(int i = len - 1; i >= 0; i--){
            if(a[last_dg + i] > b[i]) return 1;
            if(a[last_dg + i] < b[i]) return 0;
        }
        return 1;
    }
    void erase_pre0(int a[], int& len){
        while(len && a[len] == 0) len--;
    }
    void add(){
        int lc = max(la, lb);
        for(int i = 0; i < la; i++){
            C[i] += A[i] + B[i];
            C[i + 1] += C[i]/10;
            C[i] = C[i] % 10;
        }
        erase_pre0(C, lc);
        Print(C, lc);
    }
    void sub(){
        if(!(greater_eq(A, B, 0, lb))) {
            cout <<"-";
            swap(A, B);
        }
        int lc = max(la, lb);
        for(int i = 0; i < la; i++){
            C[i] += A[i] - B[i];
            if(C[i] < 0){
                C[i + 1] -= 1;
                C[i] += 10;
            }
        }
        erase_pre0(C, lc);
        Print(C, lc);
    }
    void mul(){
        int lc = la + lb;
        for(int i = 0; i < la; i++){
            for(int j = 0; j < lb; j++){
                C[i + j] += A[i]*B[j];
                C[i + j + 1] += C[i + j]/10;
                C[i + j] = C[i + j]%10;
            }
        }
        erase_pre0(C, lc);
        Print(C, lc);
    }
    void div(){
        int lc = max(la, lb);
        int ld = lc;
        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;
            }
        }
        erase_pre0(C, lc);
        erase_pre0(D, ld);
        Print(C, lc);
        Print(D, ld);
    }
};
  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值