大整数的存储与加减乘除四则运算

 当需要计算的整数或计算结果可能会超出long long 所能表示的范围时,应该用大整数来存储和计算(Java里面有BigInteger来存储大整数,这里讨论的是C++语言)。

大整数的存储形式是下面这个结构体(包含了构造函数):

// 大整数结构体
struct bign{
    int d[1000];
    int len;

    bign(){
        memset(d, 0, sizeof(d));
        len = 0;
    }
};

首先以字符串的形式读去数据,然后将字符串逐个逆序字符存入d[]数组(可以采用用reverse函数将字符串进行反转,然后正序逐个赋值),len记录整数的长度。

change()转换函数(完成字符串到bign结构体的转换)

// 将整数的字符串形式转换成bign结构体形式
bign change(char str[]){    // 将整数转换为bign
    bign a;
    a.len = strlen(str);        // bign的长度就是字符串的长度
    for (int i = 0; i < a.len; i++){
        a.d[i] = str[a.len - i - 1] - '0';        // 逆着赋值
    }
    return a;
}

在对两个大整数进行减法时要先比较减数和被减数的大小,如果减数大于被减数,则两个整数交换位置,所以还需要一个比较函数

compare()比较函数(比较两个数的大小 如果a > b,那么返回1, 如果 a < b, 返回-1,否则返回0

// 比较两个数的大小 如果a > b,那么返回1, 如果 a < b, 返回-1,否则返回0
int compare(bign a, bign b){
    if (a.len > b.len)
        return 1;            // a更大
    else if (a.len < b.len)
        return -1;
    else{
        for (int i = a.len - 1; i >= 0; i--){
            if (a.d[i] > b.d[i])                // 只要有一位a大,则a更大
                return 1;
            else if (a.d[i] < b.d[i])
                return -1;
        }
        return 0;            // 两数相等
    }
}

1. 大整数的加法:

将该位上的两个数字以及来自低位的进位相加,得到的结果的个位表示该位结果,十位数作为新的进位

bign add(bign a, bign b){            // 高精度 a + b
    bign c;
    int carry = 0;            // carry是进位
    for (int i = 0; i < a.len || i < b.len; i++){    // 以较长的为界限
        int temp = a.d[i] + b.d[i] + carry;            // 两个对应位与进位相加
        c.d[c.len++] = temp % 10;            // 个位数为该位结果
        carry = temp / 10;                    // 十位数为新的进位
    }
    if (carry != 0){
        c.d[c.len++] = carry;            // 如果最后进位不为0,则直接赋给结果的最高位
    }
    return c;
}

2. 大整数之间的减法

使用下面这个函数前要先比较两数绝对值大小,如果被减数小于减数,需要交换两个变量,然后输出符号,再使用sub函数

 1 bign sub(bign a, bign b){
 2     bign c;
 3     for (int i = 0; i < a.len || i < b.len; i++){
 4         if (a.d[i] < b.d[i]){        // 如果不够减
 5             a.d[i + 1]--;            // 向高位借位
 6             a.d[i] += 10;            // 当前位加10
 7         }
 8         c.d[c.len++] = a.d[i] - b.d[i];        // 减法结果作为当前结果
 9     }
10     while (c.len - 1 >= 1 && c.d[c.len - 1] == 0){
11         c.len--;            // 去除高位的0,同时至少保留一位最低位
12     }
13     return c;
14 }

3. 大整数和整数的乘法(一个大整数乘以一个整数):

  用从大整数a 的低位开始,用大整数的每一位乘以给定的整数,然后加上进位,每一次的结果对10取余就是结果变量c在当前索引的数值,每一次的结果除以10作为新的进位,遍历完 a 的所有数位后,如果表示进位的变量不为零,则应该将这个变量逐位的加到 c 的最高位,直到这个进位变量为0

 1 bign multi(bign a, int b){
 2     bign c;
 3     int carry = 0;
 4     for (int i = 0; i < a.len; i++){
 5         int temp = a.d[i] * b + carry;
 6         c.d[c.len++] = temp % 10;
 7         carry = temp / 10;                // 高位部分作为新的进位
 8     }
 9     while (carry != 0){
10         c.d[c.len++] = carry % 10;
11         carry /= 10;
12     }
13     return c;
14 }

  如果两个整数刚好一正一负,那么先输出符号,然后将绝对值带入函数计算。

4. 大整数和整数的除法(一个大整数除以一个整数):

 1 bign divide(bign a, int b, int &r){            // r为余数
 2     bign c;    
 3     c.len = a.len;
 4     for (int i = a.len - 1; i >= 0; i--){    // 从高位开始
 5         r = r * 10 + a.d[i];        // 和上一位遗留的余数组合
 6         if (r < b)
 7             c.d[i] = 0;        // 不够除,该位为0
 8         else{
 9             c.d[i] = r / b;    //
10             r  = r % b;        // 获得新的余数
11         }
12     }
13     while (c.len - 1 >= 1 && c.d[c.len - 1] == 0){
14         c.len--;            // 去除高位的0,同时至少保留一位最低位
15     }
16     return c;
17 }

练习题:PAT B1017    PAT A1023

本博客大部分取自胡凡的《算法笔记》和《算法笔记上机训练》

猜你喜欢

转载自www.cnblogs.com/hi3254014978/p/12233200.html
今日推荐