基础算法--高精度加减法

3 阅读3分钟

高精度加减法


我们在运算时,需要为变量赋予不同的数据类型,例如int,double,long long等。但是,当我们在面对一些极大的数字时,现有的数据类型并不支持我们进行加减运算。此时,我们可以运用高精度的算法进行计算。

高精度加减法的原理就是:我们将数字的每一位都拆开,装入一个数组,然后对数组的每一位单独进行运算。然而,我们在输入数据时一般是输入一整个数字而不会一位一位地输入,那么该怎么办呢?

解决方案是先把数字存入一个string中,然后将string中的每一位依次存入数组中。中间字符到整数的转化,我们可以运用ASCII码的一个技巧,任意数字字符减去字符0的结果就是对应的整数,例如'8' - '0' = 8。

针对加法,我们按位相加,记得进位即可。 下面是详细的代码示例:

#include <iostream>
#include <cmath>
#include <string>
using namespace std;
//高精度加法:两个不超过1万位的数相加
int a[10010], b[10010], c[10010];
string s1, s2;

int init(int x[]){ //读入数据,并且返回数据的位数
    string s;
    cin >> s;
    int l = s.size();   //数据的长度

    for(int i = 0; i < l; ++i){ //倒着存,x[0]存储个位数字
        x[i] = s[l - 1 -i] - '0';   //字符数字减去字符0,就是对应数值
    }

    return l;
}

int main(){
    int la = init(a);   //处理数据1
    int lb = init(b);   //处理数据2
    int lc = max(la, lb) + 1;   //结果的最大位数(最高位可能进位1,如果没有进位,则填入前导0)

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

    //去掉前导0(0024-->24)
    --lc;   //下标是0~lc-1,所以这里直接减一
    while(c[lc] == 0 && lc > 0){
        --lc;
    }//lc就是目前最高位的下标,输出的范围lc~0

    for(int i = lc; i >= 0; --i){
        cout << c[i];
    }
    printf("\n");

    return 0;
}

针对减法,我们不可以一上来就进行初始化,因为减法是有可能减出负数的,所以我们要先判断输入的s1和s2的大小关系,如果s1更小,那么要先输出一个负号然后交换s1和s2。这样就可以按位相减,记得不够减还要借位,最后去掉前导0就可以输出了。 下面是详细的代码示例:

#include <iostream>
#include <cmath>
#include <string>
using namespace std;
//高精度加法:两个不超过1万位的数相减
int a[10010], b[10010], c[10010];
string s1, s2;

int init(int x[], string s){ //读入数据,并且返回数据的位数
    int l = s.size();   //数据的长度

    for(int i = 0; i < l; ++i){ //倒着存,x[0]存储个位数字
        x[i] = s[l - 1 -i] - '0';   //字符数字减去字符0,就是对应数值
    }

    return l;
}

int main(){
    cin >> s1 >> s2;
    if((s1.size() < s2.size()) || (s1.size() == s2.size() && s1 < s2)){ //s1比s2长 或者 s1与s2按位比较,s1更大
        cout << '-';
        swap(s1, s2);
    }
    //大减小
    int la = init(a, s1);
    int lb = init(b, s2);
    int lc = max(la, lb);
    for(int i = 0; i < lc; ++i){
        c[i] += a[i] - b[i];
        if(c[i] < 0){
            c[i] += 10;
            --c[i + 1];
        }
    }

    //去掉前导0(0024-->24)
    --lc;   //下标是0~lc-1,所以这里直接减一
    while(c[lc] == 0 && lc > 0){
        --lc;
    }//lc就是目前最高位的下标,输出的范围lc~0

    for(int i = lc; i >= 0; --i){
        cout << c[i];
    }



    printf("\n");

    return 0;
}