引言
在计算机科学领域,数值计算是基础而重要的组成部分。然而,标准数据类型(如int、long long等)存在数值范围限制,无法满足大数运算的需求。本文介绍一个完整的高精度Number类实现,它可以处理任意长度的整数运算,包括加减乘除和比较操作,突破了语言原生数据类型的限制。
这是整数类!!!
这是整数类!!!
这是整数类!!!
目录
后面会出一篇文章发能处理浮点数的。
一、功能说明
可实现以下几个功能:
-
完整运算符重载:
-
算术运算符:
+,-,* -
比较运算符:
==,!=,<,>,<=,>= -
赋值运算符:
= -
流运算符:
<<,>>
-
-
精确处理:
-
自动处理前导零(如"000123"转为"123")
-
规范零的符号(强制"-0"转为"0")
-
正确处理符号组合(如正负数的加减比较)
-
-
错误处理:
-
无效字符检测(非数字字符抛出异常)
-
空字符串检测
-
-
性能优化:
-
逆序存储数字便于运算
-
乘法的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))
处理要点:
-
同步遍历两个数字
-
维护进位标志
-
直到所有数字处理完且无进位才结束
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
关键点:
-
借位处理
-
结果规范化
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;
}
比较逻辑:
-
先比较符号
-
同符号时比较绝对值
-
负数比较取反
四、接口设计(重载<<和>>)
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;
六、后话
以后还会再出一篇能处理浮点数的,还会添加以下功能:
-
除法实现:实现高精度除法
-
取模运算:扩展%运算符
-
位运算:支持大数位操作
-
浮点扩展:支持小数运算
-
多线程优化:并行化乘法运算
-
······(希望各位童鞋能提供一点思路)
最后,贴一下完整代码:
#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;
}
完结撒花(我花呢?!

被折叠的 条评论
为什么被折叠?



