大数运算之字符串模拟
|
(二)加法 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的好处。 ?还有要注意的就是要用最大的字符串(最长的字符串)来减小的字符串。这样可以保证结果用最长的字符串就可以保存,不用考虑空间的问题。 (编辑:永州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

