高精度运算【加减乘除比较】

高精度定义

高精度计算(Arbitrary Precision Arithmetic)是指超过编程语言内置数据类型(如 int、long、double)所能表示范围的数值运算。一般编程语言的数值类型有固定的存储位数,导致超出范围时可能溢出或丢失精度,因此需要使用高精度算法来处理。

出现的原因:

  • 1️⃣ 存储空间限制:int、double 等数据类型有固定的存储位数,超出范围会溢出或丢失精度。
  • 2️⃣ 浮点数误差:计算机采用二进制存储小数,导致某些十进制数无法精确表示。
  • 3️⃣ 科学/金融计算需求:很多实际应用(如金融、密码学)要求精确到几十位甚至上百位,普通数据类型无法满足

高精度模板套用:

Tip:
inline 是 C++ 关键字,用于建议编译器将函数代码直接插入调用处,以减少函数调用的开销,提高执行效率

  • 普通函数调用涉及 压栈、跳转、返回 等步骤,inline 通过内联展开(直接替换代码)避免了这些额外操作,提高执行速度 ;
  • 适合短小的函数,不适合递归函数和复杂函数;

vector 为C++标准模板库中的动态数组容器;
特点:

  • 支持自动扩容,调整大小;
  • 连续存储,可以用指针遍历
  • 支持随机访问;

方法:

  • vector v(5, 10); // 创建 5 个元素,初始值均为 10
  • vector v(5); // 定义一个大小为 5,所有元素初始化为 0 的 vector
  • v.push_back(4); // {1, 2, 3, 4},在末尾添加 4
  • v.insert(v.begin(), 0); // {0, 1, 2, 3, 4},在开头插入 0
  • v.pop_back(); // 删除最后一个元素 {0, 1, 2, 3}
  • v.erase(v.begin()); // 删除第一个元素 {1, 2, 3}
  • int last = v.back(); // 访问最后一个元素
  • int size = v.size(); // 获取元素个数
  • reverse(res.begin(), res.end());//翻转数组中元素的位置 ,使用时加上 algorithm 头文件

高精度加法

思路:

  • 传入两个动态数组,先在调用方法设置一个空的动态数数组和一个标志进位的值;
  • 然后for循环其两个动态数组的长度,然后依次从其数组的低位加起来到标志进位的值;
  • 然后将得到的值进%10取余做累加值的低位,然后将低位加起来的值/10保留到标志进位的值;
  • 然后进行后续的操作,直到没有进位或者for循环达到索引是两个动态数组的长度;
/**
*这里的传入的数据方向是高位到低位
*/
inline vector<int> add(vector<int> &a, vector<int> &b) {
    vector<int> res;
    int carry = 0; // 进位
    int lenA = a.size(), lenB = b.size();

    // 从高位到低位处理
    for (int i = 0; i < max(lenA, lenB) || carry; i++) {
        if (i < lenA) carry += a[lenA - 1 - i]; // 从高位开始加
        if (i < lenB) carry += b[lenB - 1 - i]; // 从高位开始加
        res.push_back(carry % 10); // 取当前位
        carry /= 10; // 更新进位
    }

    reverse(res.begin(), res.end()); // 反转结果以恢复高位在前

    return res; // 返回最终结果
}

高精度减法

思路:

  • 创建一个存储结果的向量和一个借位的临时变量;
  • 从数值的低位开始进行相减,然后当数值小于0时进行借位;
  • 将计算后的借位值插入存储结果的向量后面,以此类推;
  • 最后对于前导0进行置空,以及翻转结果向量;
/**
*这里的传入的数据方向是高位到低位
*/
inline vector<int> sub(vector<int> &a, vector<int> &b) {
    vector<int> res;
    int borrow = 0; // 借位
    int lenA = a.size(), lenB = b.size();

    // 从高位到低位处理
    for (int i = 0; i < lenA; i++) {
        int t = a[lenA - 1 - i] - borrow; // 从高位开始减去借位
        if (i < lenB) {
            t -= b[lenB - 1 - i]; // 减去 b 的当前位
        }

        if (t < 0) {
            t += 10; // 借位
            borrow = 1;
        } else {
            borrow = 0;
        }

        res.push_back(t); // 存储当前位的结果
    }

    // 去掉前导零
    while (res.size() > 1 && res.back() == 0) {
        res.pop_back();
    }

    reverse(res.begin(), res.end()); // 反转结果以恢复高位在前

    return res;
}

高精度乘法(高精度数组,低位数值相除)

思路:(这里建议书写一个乘法运算,240*3)

  • 传入高精度数组和对应的另一个低精度的乘数;
  • 创建一个存储结果的动态数组和一个标志进位;
  • 遍历从高精度低位开始依次乘以低精度乘数,然后模拟高精度加法进行取余放低位,剩下进行取模
  • 依次循环往复,直到索引到达动态数组高位;
 /**
*这里的传入的数据方向是高位到低位
*/
inline vector<int> mul(vector<int> &a, int b) {
    vector<int> res;  // 存储结果的向量
    int t = 0;  // 进位
    int len = a.size();  // 输入向量的长度

    for (int i = len - 1; i >= 0; i--) {  // 从高位到低位处理
        t += a[i] * b;  // 乘以 b
        res.push_back(t % 10);  // 取当前位
        t /= 10;  // 更新进位
    }

    while (t) {  // 处理剩余的进位
        res.push_back(t % 10);
        t /= 10;
    }

    reverse(res.begin(), res.end()); // 反转结果以恢复高位在前

    return res;  // 返回乘法结果
}

高精度除法(高精度数组,低位数值相除)

思路:(这里建议书写一个除法运算240/3)

  • 初始先创建存储结果的向量和余数变量;
  • 循环遍历从高位开始,进行余数*10再加向量中的索引位;
  • 进行判断余数是否大于被除数,如果是进行push其相除的计算结果,后更新余数;否则更新余数为0;
  • 去除前导0并最后返回结果;
/**
*这里的传入的数据方向是高位到低位
*/
inline vector<int> div(vector<int> &a, int b) {
    vector<int> res;  // 存储结果的向量
    int r = 0;  // 余数
    int len = a.size();  // 输入向量的长度

    for (int i = 0; i < len; i++) {  // 从高位到低位处理
        r = r * 10 + a[i];  // 将当前位加入余数
        if (r >= b) {  // 如果余数大于等于除数
            res.push_back(r / b);  // 计算商并存入结果
            r %= b;  // 更新余数
        } else {
            res.push_back(0);  // 商为0
        }
    }

    // 去掉前导零
    while (res.size() > 1 && res.front() == 0) {
        res.erase(res.begin());  // 移除前导零
    }

    return res;  // 返回除法结果
}

高精度比较

思路:

  • 先进行动态数组长度的判断;
  • 长度相同依次从每一个位进行比较;
 inline int compare(vector<int> &a, vector<int> &b) {
     int lenA = a.size();
     int lenB = b.size();
     if (lenA != lenB) {  // 长度不同
         return lenA - lenB;  // 返回长度差
     } else {  // 长度相同
         for (int i = lenA - 1; i >= 0; i--) {
             if (a[i] != b[i]) {  // 从高位比较
                 return a[i] - b[i];  // 返回差值
             }
         }
         return 0;  // 相等
     }
 }

你可能感兴趣的:(学习心得,算法,高精度)