• 「C++」论高精度


    大家好,我是Charzie。在编程领域,高精度计算是一个常见的问题。当标准的整型或浮点型无法满足我们的计算需求时,高精度计算就显得尤为重要。在C++中,虽然标准库没有直接提供高精度数据类型,但我们可以通过一些技巧和工具类来实现高精度计算。

    为什么需要高精度?

    在编程中,我们经常会遇到一些大数计算的问题,比如大数的加减乘除、大素数判断等。这些问题的标准数据类型(如intlong long等)往往无法处理,因为它们有数据范围的限制。此时,我们就需要使用高精度计算来解决问题。

    C++中实现高精度的方法

    在C++中,实现高精度计算的方法主要有两种:使用数组模拟和使用高精度库。

    使用数组模拟

    我们可以使用数组来模拟高精度数。每个数组元素存储高精度数的一位,然后通过模拟手工计算的过程来实现高精度计算。这种方法虽然比较繁琐,但能够很好地理解高精度计算的原理。

    例如,对于高精度加法,我们可以从低位到高位依次相加,注意处理进位问题。对于高精度乘法,我们可以使用竖式乘法的思想,将两个高精度数相乘的结果逐位计算并存储。

    使用高精度库

    为了简化高精度计算的实现,我们可以使用一些现成的高精度库,如GMPGNU Multiple Precision Arithmetic Library)或Boost.Multiprecision库。这些库提供了丰富的高精度数据类型和运算函数,可以大大简化高精度计算的实现。

    例如,使用GMP库,我们可以直接定义高精度整数类型,并进行加减乘除等运算,而无需关心底层的实现细节。

    高精度计算的应用场景

    高精度计算在很多领域都有广泛的应用,比如密码学、大数据分析、科学计算等。在密码学中,高精度计算可以用于实现公钥密码算法中的大数运算;在大数据分析中,高精度计算可以帮助我们处理海量的数据;在科学计算中,高精度计算可以提高计算的精度和可靠性。

    高精度结构体:Bigint

    这算是送给大家的一个礼物,是使用C++进行编写的结构体Bigint,集加、减、乘、除、输入、输出为一体。

    #intclude<bits/stdc++.h>
    struct Bigint {  
        std::vector<int> digits; // 存储每一位数字,低位在前  
        bool isNegative;         // 标记是否为负数  
        Bigint() : isNegative(false) {}  
      
        // 构造函数,从字符串构造Bigint  
        Bigint(const std::string& str) : isNegative(false) {  
            if (str[0] == '-') {  
                isNegative = true;  
                for (size_t i = 1; i < str.length(); ++i) {  
                    digits.push_back(str[i] - '0');  
                }  
            } else {  
                for (size_t i = 0; i < str.length(); ++i) {  
                    digits.push_back(str[i] - '0');  
                }  
            }  
            std::reverse(digits.begin(), digits.end()); // 将数字反转,使得高位在后,方便计算  
        }  
      
        // 加法  
        Bigint operator+(const Bigint& b) const {  
            // 假设两个数都是正数,负数情况可以通过取反来处理  
            Bigint result;  
            int carry = 0;  
            size_t maxLength = std::max(digits.size(), b.digits.size());  
            for (size_t i = 0; i < maxLength || carry; ++i) {  
                int aDigit = i < digits.size() ? digits[i] : 0;  
                int bDigit = i < b.digits.size() ? b.digits[i] : 0;  
                int sum = aDigit + bDigit + carry;  
                carry = sum / 10;  
                result.digits.push_back(sum % 10);  
            }  
            while (result.digits.size() > 1 && result.digits.back() == 0) {  
                result.digits.pop_back(); // 去除前导零  
            }  
            return result;  
        }  
      
        // 减法(假设this >= b)  
        Bigint operator-(const Bigint& b) const {  
            Bigint result;  
            int borrow = 0;  
            for (size_t i = 0; i < digits.size(); ++i) {  
                int aDigit = digits[i];  
                int bDigit = i < b.digits.size() ? b.digits[i] : 0;  
                int diff = aDigit - bDigit - borrow;  
                if (diff < 0) {  
                    diff += 10;  
                    borrow = 1;  
                } else {  
                    borrow = 0;  
                }  
                result.digits.push_back(diff);  
            }  
            while (result.digits.size() > 1 && result.digits.back() == 0) {  
                result.digits.pop_back(); // 去除前导零  
            }  
            return result;  
        }  
      
        // 乘法(简化版,未优化)  
        Bigint operator*(const Bigint& b) const {  
            Bigint result;  
            result.digits.resize(digits.size() + b.digits.size(), 0);  
            for (size_t i = 0; i < digits.size(); ++i) {  
                for (size_t j = 0; j < b.digits.size(); ++j) {  
                    int product = digits[i] * b.digits[j];  
                    result.digits[i + j] += product / 10; // 进位部分加到更高位上  
                    result.digits[i + j + 1] += product % 10; // 个位数加到下一位上  
                }  
            }  
            for (size_t i = 0; i < result.digits.size() - 1; ++i) { // 处理进位  
                if (result.digits[i] >= 10) {  
                    result.digits[i + 1] += result.digits[i] / 10;  
                    result.digits[i] %= 10;  
                }  
            }  
            while (result.digits.size() > 1 && result.digits.back() == 0) {  
                result.digits.pop_back(); // 去除前导零  
            }  
            return result;  
        }  
      
        // 输入输出  
        friend std::istream& operator>>(std::istream& in, Bigint& b) {  
            std::string s;  
            in >> s;  
            b = Bigint(s);  
            return in;  
        }  
      
        friend std::ostream& operator<<(std::ostream& out, const Bigint& b) {  
            if (b.isNegative) out << '-';  
            for (auto it = b.digits.rbegin(); it != b.digits.rend(); ++it) {  
                out << *it;  
            }  
            return out;  
        }  
    };  
      
    // 示例使用  
    int main() {  
        Bigint a, b, sum, diff, prod;  
        std::cin >> a >> b;  
        sum = a + b;  
        diff = a - b; // 假设a >= b  
        prod = a * b;  
        std::cout << "Sum: " << sum << std::endl;  
        std::cout << "Difference: " << diff << std::endl;  
        std::cout << "Product: " << prod << std::endl;  
        return 0;  
    }
    

    结语

    高精度计算是编程领域的一个重要主题,它可以帮助我们解决标准数据类型无法处理的大数计算问题。在C++中,我们可以通过数组模拟或使用高精度库来实现高精度计算。随着技术的发展,高精度计算将在更多的领域得到应用,为我们的生活和工作带来更多的便利和可能性。

    最后,我想说的是,高精度计算虽然有一定的难度,但只要我们掌握了基本的原理和方法,并多加练习和实践,就一定能够熟练掌握这一技能。希望这篇博客能够对大家有所帮助,让我们一起探索高精度计算的奥秘吧!


    __EOF__

  • 本文作者: charzie-blog
  • 本文链接: https://www.cnblogs.com/charzie-blog/p/18233596
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    Git Tortoise安装 CodeHub
    复制带随机指针的链表
    Shell编程之定时任务
    PCL-1.12.1(C++)将kitti 点云Velodyne 数据集bin转化pcd并可视化
    报名仅剩十天!又一开发者公布高分方案源代码,助力软件杯选手高效解题
    播放器事件/与JS交互
    实验六 并行口8255的使用—LED静态显示
    iOS关于搜索不规则瀑布流布局的实现小结
    vscode上搭建go开发环境
    react笔记
  • 原文地址:https://www.cnblogs.com/charzie-blog/p/18233596