首先来看一下题目:
// 大整数类型
class BigInt
{
public:
BigInt(string str) :strDigit(str){}
private:
string strDigit; // 使用字符串存储大整数
};
// 打印函数
ostream& operator<<(ostream &out, const BigInt &src);
// 大数加法
BigInt operator+(const BigInt &lhs, const BigInt &rhs);
// 大数减法
BigInt operator-(const BigInt &lhs, const BigInt &rhs);
int main()
{
BigInt int1("28937697857832167849697653231243");
BigInt int2("9785645649886874535428765");
cout << int1 + int2 << endl;
cout << int1 - int2 << endl;
return 0;
}
因为是用自定义类型来实现两个对象的相加相减和输出,所以我们必须为其提供相应的运算符重载函数。
首先说一下我看到这道题的时候的感受吧!最开始看到的时候觉得真的是一脸懵逼,这该怎么写?仔细审了一遍题之后,理解有点偏差。最开始想的是既然是string类型的字符串,那+应该就是所谓的字符串连接,但看到减法的时候就觉得不对了。所以审题一定要审清楚。这道题的意思就是:因为普通数据类型无法存储这么大的数据,所以利用C++的string类来存储,也就是将大数存为字符串类型。但是相应的加减操作仍应遵循十进制数的加减法,也应考虑到从最后一位开始相加相减,还有进位和借位的问题。
#include<iostream>
#include<string>
using namespace std;
// 大整数类型
class BigInt
{
public:
BigInt(string str) :strDigit(str){}
private:
string strDigit; // 使用字符串存储大整数
//声明友元函数
friend ostream& operator<<(ostream &out, const BigInt &src);
friend BigInt operator+(const BigInt &lhs, const BigInt &rhs);
friend BigInt operator-(const BigInt &lhs, const BigInt &rhs);
};
// 打印函数
ostream& operator<<(ostream &out, const BigInt &src)
{
out << src.strDigit << endl;
return out;
}
// 大数加法
BigInt operator+(const BigInt &lhs, const BigInt &rhs)
{
string result;
bool flag = false; //标志位
int lhs_len = lhs.strDigit.size();
int rhs_len = rhs.strDigit.size();
//循环按位加
for (; lhs_len >= 0 && rhs_len >= 0; --lhs_len, --rhs_len)
{
int ret = lhs.strDigit[lhs_len] - '0' + rhs.strDigit[rhs_len] - '0';//得到同位数的和
if (flag) //进入条件:上一位有进位
{
ret += 1;
flag = false;
}
if (ret >= 10) //有进位
{
ret %= 10;
flag = true;
}
result.push_back(ret + '0');//入存放结果的string
}
//如果rhs字符串先结束
if (lhs_len >= 0)
{
while (lhs_len >= 0)
{
int ret = lhs.strDigit[lhs_len] - '0';
if (flag)
{
ret += 1;
flag = false;
}
if (ret >= 10)
{
ret %= 10;
flag = true;
}
result.push_back(ret + '0');
lhs_len--;
}
}
else if (rhs_len >= 0) //如果lhs字符串先结束
{
while (rhs_len >= 0)
{
int ret = rhs.strDigit[rhs_len] - '0';
if (flag)
{
ret += 1;
flag = false;
}
if (ret >= 10)
{
ret %= 10;
flag = true;
}
result.push_back(ret + '0');
rhs_len--;
}
}
if (flag) //判断最高位是否有进位
{
result.push_back('1');
}
reverse(result.begin(), result.end()); //逆置
return result;
}
// 大数减法
BigInt operator-(const BigInt &lhs, const BigInt &rhs)
{
string result;
bool flag = false;//借位标志
bool minor = false;//正负数标志
string maxStr = lhs.strDigit;//默认lhs字符串为长的字符串
string minStr = rhs.strDigit;//默认rhs字符串为短的字符串
if (maxStr.length() < minStr.length())//判断maxStr和minStr的长度
{
maxStr = rhs.strDigit;
minStr = lhs.strDigit;
minor = true;
}
else if (maxStr.length() == minStr.length())//长度相等
{
if (maxStr < minStr)//调用字符串"<",比较字符串大小
{
maxStr = rhs.strDigit;
minStr = lhs.strDigit;
minor = true;
}
else if (maxStr == minStr) //调用字符串"相等"函数
{
return string("0");//相等直接返回'0',表示相减的差为0
}
}
int lhs_len = maxStr.size();
int rhs_len = minStr.size();
for (; lhs_len >= 0 && rhs_len >= 0; --lhs_len, --rhs_len)
{
int ret = maxStr[lhs_len] - minStr[rhs_len];
if (flag)
{
ret -= 1;
flag = false;
}
if (ret < 0)
{
ret += 10;
flag = true;
}
result.push_back(ret + '0');
}
while (lhs_len >= 0)
{
int ret = maxStr[lhs_len]-'0';
if (flag)
{
ret -= 1;
flag = false;
}
if (ret < 0)
{
ret += 10;
flag = true;
}
result.push_back(ret + '0');
lhs_len--;
}
if (minor)//判断正负
{
result.push_back('-');
}
reverse(result.begin(), result.end());
return result;
}
int main()
{
BigInt int1("28937697857832167849697653231243");
BigInt int2("9785645649886874535428765");
cout << int1 + int2 << endl;
cout << int1 - int2 << endl;
return 0;
}
换一组测试:
总结:这类问题一定要全面考虑,拿我们数学计算时会遇到的各种问题来完善代码功能。比如考虑按位,从后往前,进位和借位的问题,加法时最高位是否有进位的问题,减法万一是小数减大数结果是负数的问题。这些都应该考虑到,多些代码吧!加油^-^