网易笔试题:实现大数的加法!

首先来看一下题目:

// 大整数类型
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
#include
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;
}

网易笔试题:实现大数的加法!_第1张图片

 换一组测试:

网易笔试题:实现大数的加法!_第2张图片

总结:这类问题一定要全面考虑,拿我们数学计算时会遇到的各种问题来完善代码功能。比如考虑按位,从后往前,进位和借位的问题,加法时最高位是否有进位的问题,减法万一是小数减大数结果是负数的问题。这些都应该考虑到,多些代码吧!加油^-^

你可能感兴趣的:(网易笔试题:实现大数的加法!)