zoukankan      html  css  js  c++  java
  • 大整数的存储与加减乘除四则运算

     当需要计算的整数或计算结果可能会超出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

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

  • 相关阅读:
    复杂模拟 | 1017 模拟N个顾客M个柜台进行排队
    徒手实现lower_bound和upper_bound
    树状数组 | 1057
    动态规划 | 最长回文子串 1040
    动态规划 | 背包问题 1068
    动态规划 | 对输入进行hash处理的LIS 1045
    总结那些有默认margin,padding值的html标签
    javascript 的七种基本数据类型
    牛客网笔试题整理
    JavaScript 的数据结构与算法
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/12233200.html
Copyright © 2011-2022 走看看