高精度类的设计与实现

引言

在计算机科学领域,数值计算是基础而重要的组成部分。然而,标准数据类型(如int、long long等)存在数值范围限制,无法满足大数运算的需求。本文介绍一个完整的高精度Number类实现,它可以处理任意长度的整数运算,包括加减乘除和比较操作,突破了语言原生数据类型的限制。

这是整数类!!!

这是整数类!!!

这是整数类!!!

目录

引言

一、功能说明

 二、内部实现

2.1 数据存储

2.2 核心算法

2.2.1 加法实现

 

2.2.2 减法实现

 

2.2.3 乘法实现

 

三、运算符重载

3.1 算术运算符

 

3.2 比较运算符

 

四、接口设计(重载<<和>>)

4.1 输入输出

4.2 构造函数 

五、应用示例

5.1 基本运算

 5.2 比较运算

5.3 流式操作

六、后话


后面会出一篇文章发能处理浮点数的

一、功能说明

可实现以下几个功能:

  1. 完整运算符重载

    • 算术运算符:+-*

    • 比较运算符:==!=<><=>=

    • 赋值运算符:=

    • 流运算符:<<>>

  2. 精确处理

    • 自动处理前导零(如"000123"转为"123")

    • 规范零的符号(强制"-0"转为"0")

    • 正确处理符号组合(如正负数的加减比较)

  3. 错误处理

    • 无效字符检测(非数字字符抛出异常)

    • 空字符串检测

  4. 性能优化

    • 逆序存储数字便于运算

    • 乘法的O(n²)优化实现

    • 避免不必要的拷贝

 二、内部实现

2.1 数据存储

private:
    vector<int> digits;  // 数字逆序存储(个位在前)
    bool isPositive;

采用逆序存储设计:

  • 数字"12345"实际存储为[5,4,3,2,1]

  • 优点:便于处理进位/借位操作

  • 符号单独用isPositive标记

2.2 核心算法

2.2.1 加法实现

vector<int> addAbs(const vector<int>& a, const vector<int>& b) const {
    vector<int> res;
    int carry = 0;
    for (int i = 0; i < max(a.size(), b.size()) || carry; ++i) {
        int sum = carry;
        if (i < a.size()) sum += a[i];
        if (i < b.size()) sum += b[i];
        res.push_back(sum % 10);
        carry = sum / 10;
    }
    return res;
}

 

时间复杂度:O(max(n,m))
处理要点:

  1. 同步遍历两个数字

  2. 维护进位标志

  3. 直到所有数字处理完且无进位才结束

2.2.2 减法实现

vector<int> subAbs(const vector<int>& a, const vector<int>& b) const {
    vector<int> res;
    int borrow = 0;
    for (int i = 0; i < a.size(); ++i) {
        int diff = a[i] - borrow;
        if (i < b.size()) diff -= b[i];
        borrow = diff < 0 ? 1 : 0;
        res.push_back(diff < 0 ? diff + 10 : diff);
    }
    // 去除结果前导零...
    return res;
}

 

前提条件:a ≥ b
关键点:

  1. 借位处理

  2. 结果规范化

2.2.3 乘法实现

vector<int> mulAbs(const vector<int>& a, const vector<int>& b) const {
    vector<int> res(a.size() + b.size(), 0);
    for (int i = 0; i < a.size(); ++i) {
        int carry = 0;
        for (int j = 0; j < b.size() || carry; ++j) {
            long long product = res[i + j] + carry;
            if (j < b.size()) product += a[i] * b[j];
            res[i + j] = product % 10;
            carry = product / 10;
        }
    }
    // 去除前导零...
    return res;
}

 

采用竖式乘法优化:

  • 时间复杂度O(n²)

  • 预分配足够空间

  • 双重循环处理每位相乘

三、运算符重载

3.1 算术运算符

Number operator+(const Number& other) const {
    if (isPositive == other.isPositive) {
        // 同号相加...
    }
    // 异号转为减法...
}

Number operator-(const Number& other) const {
    Number temp = other;
    temp.isPositive = !temp.isPositive;  // 巧用加法实现减法
    return *this + temp;
}

 

符号处理规则:

  • 同号:绝对值相加,符号不变

  • 异号:绝对值相减,结果取较大数的符号

3.2 比较运算符

bool operator<(const Number& other) const {
    if (isPositive != other.isPositive) {
        return !isPositive;  // 负数<正数
    }
    return isPositive ? isAbsLess(digits, other.digits) 
                     : isAbsLess(other.digits, digits);
}

bool operator==(const Number& other) const {
    return isPositive == other.isPositive && digits == other.digits;
}

 

比较逻辑:

  1. 先比较符号

  2. 同符号时比较绝对值

  3. 负数比较取反

四、接口设计(重载<<和>>)

4.1 输入输出

friend istream& operator>>(istream& is, Number& num) {
    string s;
    is >> s;
    num = Number(s);  // 调用构造函数
    return is;
}

friend ostream& operator<<(ostream& os, const Number& num) {
    if (!num.isPositive) os << '-';
    for (auto it = num.digits.rbegin(); it != num.digits.rend(); ++it) {
        os << *it;  // 逆序输出
    }
    return os;
}

 这里的friend是因为>>和<<的第一个参数不是Number类本身。

特性:

  • 自动处理正负号

  • 跳过前导零

  • 支持标准流式IO

4.2 构造函数 

Number(const string& s) {
    // 处理符号
    // 验证数字有效性
    // 逆序存储
    removeLeadingZeros();  // 规范化
}

输入验证:

  • 允许"+"/"-"前缀

  • 自动跳过前导零

  • 非法字符检测

五、应用示例

5.1 基本运算

Number a("12345678901234567890");
Number b("98765432109876543210");

auto sum = a + b;    // 111111111011111111100
auto diff = a - b;   // -86419753208641975320
auto product = a * b; // 巨大数值...

 5.2 比较运算

if (a > b) { /*...*/ }
if (Number("999999") <= Number("1000000")) { /*...*/ }

5.3 流式操作

Number n;
cout << "请输入数字: ";
cin >> n;
cout << "你输入的是: " << n << endl;

六、后话

以后还会再出一篇能处理浮点数的,还会添加以下功能:

  1. 除法实现:实现高精度除法

  2. 取模运算:扩展%运算符

  3. 位运算:支持大数位操作

  4. 浮点扩展:支持小数运算

  5. 多线程优化:并行化乘法运算

  6. ······(希望各位童鞋能提供一点思路) 

最后,贴一下完整代码:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
//#include<bits/stdc++.h>

using namespace std;

class Number {
private:
    vector<int> digits;  // 数字逆序存储(个位在前)
    bool isPositive;

    // 去除前导零并规范0的符号
    void removeLeadingZeros() {
        while (digits.size() > 1 && digits.back() == 0) {
            digits.pop_back();
        }
        if (digits.empty() || (digits.size() == 1 && digits[0] == 0)) {
            isPositive = true;  // 强制0为正数
        }
    }

    // 绝对值加法
    vector<int> addAbs(const vector<int>& a, const vector<int>& b) const {
        vector<int> res;
        int carry = 0;
        for (int i = 0; i < max(a.size(), b.size()) || carry; ++i) {
            int sum = carry;
            if (i < a.size()) sum += a[i];
            if (i < b.size()) sum += b[i];
            res.push_back(sum % 10);
            carry = sum / 10;
        }
        return res;
    }

    // 绝对值减法(要求a >= b)
    vector<int> subAbs(const vector<int>& a, const vector<int>& b) const {
        vector<int> res;
        int borrow = 0;
        for (int i = 0; i < a.size(); ++i) {
            int diff = a[i] - borrow;
            if (i < b.size()) diff -= b[i];
            borrow = diff < 0 ? 1 : 0;
            res.push_back(diff < 0 ? diff + 10 : diff);
        }
        while (res.size() > 1 && res.back() == 0) {
            res.pop_back();
        }
        return res;
    }

    // 绝对值乘法
    vector<int> mulAbs(const vector<int>& a, const vector<int>& b) const {
        vector<int> res(a.size() + b.size(), 0);
        for (int i = 0; i < a.size(); ++i) {
            int carry = 0;
            for (int j = 0; j < b.size() || carry; ++j) {
                long long product = res[i + j] + carry;
                if (j < b.size()) product += a[i] * b[j];
                res[i + j] = product % 10;
                carry = product / 10;
            }
        }
        while (res.size() > 1 && res.back() == 0) {
            res.pop_back();
        }
        return res;
    }

    // 绝对值比较(a < b)
    bool isAbsLess(const vector<int>& a, const vector<int>& b) const {
        if (a.size() != b.size()) return a.size() < b.size();
        for (int i = a.size() - 1; i >= 0; --i) {
            if (a[i] != b[i]) return a[i] < b[i];
        }
        return false;  // 相等
    }

public:
    // 构造函数
    Number() : digits{0}, isPositive(true) {}
    
    Number(const string& s) {
        if (s.empty()) throw invalid_argument("Empty string");

        int start = 0;
        isPositive = true;
        if (s[0] == '-') {
            isPositive = false;
            start = 1;
        } else if (s[0] == '+') {
            start = 1;
        }

        // 跳过前导零
        while (start < s.size() && s[start] == '0') {
            start++;
        }

        // 处理纯零情况
        if (start == s.size()) {
            digits = {0};
            isPositive = true;
            return;
        }

        // 验证并存储数字
        for (int i = s.size() - 1; i >= start; --i) {
            if (!isdigit(s[i])) {
                throw invalid_argument("Invalid character in number");
            }
            digits.push_back(s[i] - '0');
        }

        removeLeadingZeros();
    }

    // 赋值运算符
    Number& operator=(const Number& other) {
        if (this != &other) {
            digits = other.digits;
            isPositive = other.isPositive;
        }
        return *this;
    }

    // 算术运算符
    Number operator+(const Number& other) const {
        if (isPositive == other.isPositive) {
            Number res;
            res.digits = addAbs(digits, other.digits);
            res.isPositive = isPositive;
            res.removeLeadingZeros();
            return res;
        }
        
        if (isAbsLess(digits, other.digits)) {
            Number res;
            res.digits = subAbs(other.digits, digits);
            res.isPositive = other.isPositive;
            res.removeLeadingZeros();
            return res;
        } else {
            Number res;
            res.digits = subAbs(digits, other.digits);
            res.isPositive = isPositive;
            res.removeLeadingZeros();
            return res;
        }
    }

    Number operator-(const Number& other) const {
        Number temp = other;
        temp.isPositive = !temp.isPositive;
        return *this + temp;
    }

    Number operator*(const Number& other) const {
        Number res;
        res.digits = mulAbs(digits, other.digits);
        res.isPositive = (isPositive == other.isPositive);
        res.removeLeadingZeros();
        return res;
    }

    // 比较运算符
    bool operator==(const Number& other) const {
        return isPositive == other.isPositive && digits == other.digits;
    }

    bool operator!=(const Number& other) const {
        return !(*this == other);
    }

    bool operator<(const Number& other) const {
        if (isPositive != other.isPositive) {
            return !isPositive;  // 负数 < 正数
        }
        return isPositive ? isAbsLess(digits, other.digits) 
                         : isAbsLess(other.digits, digits);
    }

    bool operator>(const Number& other) const {
        return other < *this;
    }

    bool operator<=(const Number& other) const {
        return !(other < *this);
    }

    bool operator>=(const Number& other) const {
        return !(*this < other);
    }

    // 输入输出
    friend istream& operator>>(istream& is, Number& num) {
        string s;
        is >> s;
        num = Number(s);
        return is;
    }

    friend ostream& operator<<(ostream& os, const Number& num) {
        if (!num.isPositive) os << '-';
        for (auto it = num.digits.rbegin(); it != num.digits.rend(); ++it) {
            os << *it;
        }
        return os;
    }
};

// 测试用例
int main() {
    cout << "输入两个大数(支持正负号):" << endl;
    Number a, b;
    cin >> a >> b;

    cout << "a = " << a << "\nb = " << b << endl;
    cout << "a + b = " << a + b << endl;
    cout << "a - b = " << a - b << endl;
    cout << "a * b = " << a * b << endl;

    cout << boolalpha;
    cout << "比较结果:" << endl;
    cout << "a == b: " << (a == b) << endl;
    cout << "a != b: " << (a != b) << endl;
    cout << "a < b: " << (a < b) << endl;
    cout << "a > b: " << (a > b) << endl;
    cout << "a <= b: " << (a <= b) << endl;
    cout << "a >= b: " << (a >= b) << endl;

    return 0;
}

 完结撒花(我花呢?!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值