加入收藏 | 设为首页 | 会员中心 | 我要投稿 大连站长网 (https://www.0411zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

大数运算之字符串模拟

发布时间:2021-05-17 05:30:13 所属栏目:大数据 来源:网络整理
导读:副标题#e# ? 相信大家被特别大的两个数据做运算折磨过。当两个操作数或者运算结果超过类型的表示范围后会有意想不到的错误,这时候我们的电脑还不如我们高中用过的科学计算器,这是作为一个程序员所不能忍受的。所以我们得找到其他的方式来计算。这就是我们

(二)加法

BigData?BigData::operator+(?BigData&?d)
{

	if?(!_IsINT64OverFlow()?&&?!d._IsINT64OverFlow()?
		&&?(_value?+?d._value)?<=?Max_INT64?&&?(_value?+?d._value)?>=?Min_INT64)
	{
		_value?+=?d._value;
	}
	else
	{
		OverflowFlag?=?true;
		_strvalue?=?Add(_strvalue,?d._strvalue);
	}
	return?*this;
}
string?Add(string&?left,?string&?right)
{
	if?(left[0]?!=?right[0])//符号不等
	{
		if?(left[0]?==?'+')
		{
			right[0]?=?'+';
			return?Sub(left,?right);
		}
		else
		{
			left[0]?=?'+';
			return?Sub(right,?left);
		}
	}
	else
	{
		int?lsize?=?left.size();
		int?rsize?=?right.size();
		if?(lsize?==?rsize)
		{
			int?carry?=?0;
			while?(--lsize?&&?--rsize)
			{
				char?tmp?=?left[lsize];
				left[lsize]?=?(left[lsize]?-?'0'?+?right[rsize]?-?'0')?%?10?+?carry?+?'0';
				carry?=?(tmp?-?'0'?+?right[rsize]?-?'0')?/?10;
			}
			if?(carry?==?1)
			{
				left.insert(1,?"1");
			}
			return?left;
		}
		else
		{
			if?(lsize?>?rsize)
			{
				int?carry?=?0;//进位
				while?(--lsize?&&?--rsize)//不能为--rsize&&-lsize
				{
					char?tmp?=?left[lsize];
					left[lsize]?=?(left[lsize]?-?'0'?+?right[rsize]?-?'0')?%?10?+?carry?+?'0';
					carry?=?(tmp?-?'0'?+?right[rsize]?-?'0')?/?10;
				}
				while?(carry?==?1)
				{
					left[lsize]?=?left[lsize]?+?carry;
					carry?=?(left[lsize]?-?'0'?+?carry)?/?10;
					lsize--;
				}
				
				return?left;
			}
			else
			{
				int?carry?=?0;
				while?(--rsize?&&?--lsize)//注意不能为--lsize&&--rsize,
					//当lsize为1时不执行--lsize直接跳出
				{
					char?tmp?=?right[rsize];
					right[rsize]?=?(left[lsize]?-?'0'?+?right[rsize]?-?'0')?%?10?
						+?'0'?+?carry;
					carry?=?(tmp?-?'0'?+?left[lsize]?-?'0')?/?10;
				}
				while?(carry?==?1)//当进位为1就一直往前加进位
				{
					right[rsize]?=?right[rsize]?+?carry;
					carry?=?(right[rsize]?-?'0'?+?carry)?/?10;
					rsize--;
				}
				return?right;
			}
			
		}
	}
}

? 加减乘除法都是用+-*/的重载来实现,实现时自己写的ADD,SUB,MUL,DIV。+调用ADD,-调用SUB,*调用MUL,/调用DIV。以后+-*/的重载函数我就不贴出来了,换个调用函数就行。这样的话方便以后的相互调用,只需要修改一下符号位。因为乘法是用加法模拟的,除法使用减法模拟的,减法用加法模拟的,按理来说我们使用加法就可以实现所有的运算。但是那个效率真的是惨不忍睹。

?在这里,ADD的算法核心就是要保存低位向高位的进位。和我们手算是一样的。从两个字符串的最后一位开始往前相加,直到有一个字符串遇到_strvalue[0]的字符位为止,最后还要记得把最后的进位加上。在这里要考虑被加数加上进位以后还有进位的情况,所以在这我们使用了while来循环加。不用担心字符串的空间不够,因为两个位数一样的数相加,最多进位为1.



(三)减法

string?Sub(string&?left,?string&?right)
{
	if?(left[0]?!=?right[0])
	{
		if?(left[0]?==?'+')
		{
			right[0]?=?'+';
			return?Add(left,?right);
		}
		else
		{
			right[0]?=?'-';
			return?Add(left,?right);
		}
	}
	else
	{
		int?lsize?=?left.size();
		int?rsize?=?right.size();
		if?(lsize?==?rsize)
		{
			int?borrow?=0;
			while?(--lsize?&&?--rsize)
			{
				
				if?(left[lsize]?<?right[rsize])
				{
					left[lsize]?=?left[lsize]?+?10?-?right[rsize]?-?borrow?+?'0';
					borrow?=?1;
				}
				else
				{
					left[lsize]?=?left[lsize]?-?right[rsize]?-?borrow?+?'0';
					borrow?=?0;
				}
			}
			return?left;
		}
		else?if?(lsize?>?rsize)
		{
			int?borrow?=?0;
			while?(--lsize?&&?--rsize)
			{
				if?(left[lsize]?<?right[rsize])
				{
					left[lsize]?=?left[lsize]?+?10?-?right[rsize]?-?borrow?+?'0';
					borrow?=?1;
				}
				else
				{
					left[lsize]?=?left[lsize]?-?right[rsize]?-?borrow?+?'0';
					borrow?=?0;
				}
			}
			while?(?borrow==1?)
			{
				if?(left[lsize]?==?'0')
				{
					left[lsize]?=?left[lsize]?-?'0'?+?10?-?borrow?+?'0';//若借位为0,
					//向更高位借位,eg:1000-10
					lsize--;
				}
				else
				{
					left[lsize]?=?left[lsize]?-?'0'?-?borrow?+?'0';
					borrow?=?0;
				}

			}
			
			return?left;
		}
		else
		{
			int?borrow?=?0;
			while?(--rsize?&&?--lsize)
				//得先让rsize--,若--lsize为0;将不会执行--rsize;
			{
				if?(right[rsize]?<?left[lsize])
				{
					right[rsize]?=?right[rsize]?+?10?-?left[lsize]?-?borrow?+?'0';
					borrow?=?1;
				}
				else
				{
					right[rsize]?=?right[rsize]?-?left[lsize]?-?borrow?+?'0';
					borrow?=?0;
				}
			}
			while?(borrow?==?1)
			{
				if?(right[rsize]?==?'0')
				{
					right[rsize]?=?right[rsize]?-?'0'?+?10?-?borrow?+?'0';//若借位为0,
					//向更高位借位,eg:1000-10
					rsize--;
				}
				else
				{
					right[rsize]?=?right[rsize]?-?'0'?-?borrow?+?'0';
					borrow?=?0;
				}

			}
			return?right;
		}
	}
}

? 减法的算法核心和加法差不多,每次从两个字符串的最后一位开始计算。要定义一个借位,低位向高位的借位。只要借位borrow为1就一直循环借位。

加法和减法之间可以相互调用,当一个正数加一个负数时就可以调用减法,会很方便,而且易懂。这里就体现了我们封装ADD,SUB,MUL,DIV的好处。

?还有要注意的就是要用最大的字符串(最长的字符串)来减小的字符串。这样可以保证结果用最长的字符串就可以保存,不用考虑空间的问题。



(编辑:大连站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!