您的位置:首页 > 其它

也来实现长整数得四则运算

2009-09-14 22:49 218 查看
即使我们有了64位的计算机,按内置方法我们一样处理不了大于20位的超长整数得运算,所以各种各样得办法被实现出来,闲来无事,我也弄了一块。

我选择string来保存结果,没有使用流行得串行结构,其本上就是想保留一个返回值,不过这个改起来也还是容易得,有心得朋友可以自己实现。其实目前得实现还只考虑了正确性,效率没多想,尤其是模运算,简直低效得吓人,有好得建议朋友们千万不吝赐教啊。

贴上来还有个目的就是希望朋友们能帮忙找些虫子,让我得代码能更加坚固,谢谢大家!

头文件

#ifndef CBIGINT_H_
#define CBIGINT_H_

#include <assert.h>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>

#define MAX_NUM_LEN 10240  //结果最大长度
#define MAX_FLAX_LEN 30    //浮点数最大精度

class CBigInt
{
public:
CBigInt();
~CBigInt();
public:
int add(const char* _first,const char* _second,std::string& _result); //加
int sub(const char* _first,const char* _second,std::string& _result); //减
int mul(const char* _first,const char* _second,std::string& _result); //乘
int div(const char* _first,const char* _second,std::string& _result); //除
int mod(const char* _first,const char* _second,std::string& _result); //模
int abscmp(const char* _first,const char* _second);
int absncmp(const char* _first,const char* _second,int n);

int set_max_f(int _len);
private:
int get_sigh(const char* _first,const char* _second);
int check(const char* _num);
int pure_add(const char* _first,const char* _second,std::string& _result);
int pure_sub(const char* _first,const char* _second,std::string& _result);
int pure_div(const char* _first,const char* _second,std::string& _result);
int pure_mod(const char* _first,const char* _second,std::string& _result);
int get_pure(const char* _first,const char* _second);
int mul_single(const char* _first,const char _second,std::string& _result);
private:
int m_max_len;

};
#endif


实现部分

#include "CBigInt.h"

CBigInt::CBigInt():m_max_len(MAX_FLAX_LEN)
{

}

CBigInt::~CBigInt()
{

}

int CBigInt::add(const char* _first,const char* _second,std::string& _result)
{
assert(_first!=NULL && _second!=NULL);

//检测操作数是否合法,并获取操作数的符号
int t_sigh = this->get_sigh(_first,_second);
if (t_sigh == -1)
{
return -1;
}

//预定义负号
std::string csigh = "-";

switch(t_sigh)
{
case 0://如果是二个正数相加
this->pure_add(_first,_second,_result);
break;
case 1://如果第一个操作数为负
if(this->sub(_second,_first+1,_result) == 1)
{
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
}
break;
case 2://如果第二个操作数为负
if(this->sub(_first,_second+1,_result) == 1)
{
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
}
break;
case 3://如果二个操作数都为负
this->pure_add(_first+1,_second+1,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
default:
break;
}
if ((*(_result.c_str()+1) == '-'&&_result.length()==1) ||
_result.length()==0)
{
_result = "0";
}
return 0;
}

int CBigInt::sub(const char* _first,const char* _second,std::string& _result)
{
assert(_first!=NULL && _second!=NULL);

//检测操作数是否合法,并获取操作数的符号
int t_sigh = this->get_sigh(_first,_second);
if (t_sigh == -1)
{
return -1;
}

//预定义负号
std::string csigh = "-";

int rel = 0;
switch(t_sigh)
{
case 0://如果是二个正数相减,并且被减数大于减数
rel = this->get_pure(_first,_second);
switch(rel)
{
case 0:
_result = "0";
return 0;
case 1:
this->pure_sub(_first,_second,_result);
break;
case 2:
this->pure_sub(_second,_first,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
default:
break;
}
break;
case 1://如果第一个操作数为负
this->pure_add(_first+1,_second,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
case 2://如果第二个操作数为负
this->pure_add(_first,_second+1,_result);
break;
break;
case 3://如果二个操作数都为负
rel = this->get_pure(_second+1,_first+1);
switch(rel)
{
case 0:
_result = "0";
return 0;
case 1:
this->pure_sub(_second+1,_first+1,_result);
break;
case 2:
this->pure_sub(_first+1,_second+1,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
default:
break;
}
break;
default:
break;
}
if ((*(_result.c_str()+1) == '-'&&_result.length()==1) ||
_result.length()==0)
{
_result = "0";
}

return 0;
}
int CBigInt::mul(const char* _first,const char* _second,std::string& _result)
{
assert(_first!=NULL && _second!=NULL);

//检测操作数是否合法,并获取操作数的符号
int t_sigh = this->get_sigh(_first,_second);
if (t_sigh == -1)
{
return -1;
}

int flen = strlen(_first);
int t_len = strlen(_second);
char* s_result = new char[flen+t_len+2];

std::string t_result = "";
int i = 0,j=0,k=0;
t_len--;
while (t_len>=0)
{
this->mul_single(_first,_second[t_len],t_result);
k = strlen(t_result.c_str());
memset(s_result,0,flen+t_len+2);
strncpy(s_result,t_result.c_str(),k);
while (j!=0)
{
s_result[j--+k-1]='0';
}
i++,j=i,t_len--;
this->add(_result.c_str(),s_result,_result);
}

//预定义负号
std::string csigh = "-";

switch(t_sigh)
{
case 1://如果第一个操作数为负
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
case 2://如果第二个操作数为负
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
default:
break;
}
delete [] s_result;
if ((*(_result.c_str()+1) == '-'&&_result.length()==1) ||
_result.length()==0)
{
_result = "0";
}
return 0;
}
int CBigInt::div(const char* _first,const char* _second,std::string& _result)
{
assert(_first!=NULL && _second!=NULL);

//检测操作数是否合法,并获取操作数的符号
int t_sigh = this->get_sigh(_first,_second);
if (t_sigh == -1)
{
return -1;
}

//预定义负号
std::string csigh = "-";

switch(t_sigh)
{
case 0:
this->pure_div(_first,_second,_result);
break;
case 1://如果第一个操作数为负
this->pure_div(_first+1,_second,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
case 2://如果第二个操作数为负
this->pure_div(_first,_second+1,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
case 3://如果第二个操作数为负
this->pure_div(_first+1,_second+1,_result);
break;
default:
break;
}
if ((*(_result.c_str()+1) == '-'&&_result.length()==1) ||
_result.length()==0)
{
_result = "0";
}
return 0;
}
int CBigInt::mod(const char* _first,const char* _second,std::string& _result)
{
assert(_first!=NULL && _second!=NULL);

//检测操作数是否合法,并获取操作数的符号
int t_sigh = this->get_sigh(_first,_second);
if (t_sigh == -1)
{
return -1;
}

//预定义负号
std::string csigh = "-";

switch(t_sigh)
{
case 0:
this->pure_mod(_first,_second,_result);
break;
case 1://如果第一个操作数为负
this->pure_mod(_first+1,_second,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
case 2://如果第二个操作数为负
this->pure_mod(_first,_second+1,_result);
if (*_result.c_str()!='0')
{
_result = csigh + _result;
}
break;
case 3://如果第二个操作数为负
this->pure_mod(_first+1,_second+1,_result);
break;
default:
break;
}
if ((*(_result.c_str()+1) == '-'&&_result.length()==1) ||
_result.length()==0)
{
_result = "0";
}
return 0;
}

int CBigInt::pure_add(const char* _first,const char* _second,std::string& _result)
{
int flen = strlen(_first);
int slen = strlen(_second);

int temp = 0;

int t_len = flen>slen ? flen : slen;
//动态分配存储结果数组,因为是加法,所以结果最大长度为最长操作数长度加1
//另加上一个结束符号位
char* t_result = new char[t_len+2];
if (t_result==NULL)
{
return -1;
}
memset(t_result,0,t_len+2);

flen--,slen--;
while (t_len >= 0)
{
if (flen<0)
{//如果其中以个操作数已经循环完,则结果仅加上另一个操作数
t_result[t_len] += _second[slen]+48;
}
else if (slen<0)
{
t_result[t_len] += _first[flen]+48;
}
else
{
t_result[t_len] += _first[flen] + _second[slen];
}

if (slen<0&&flen<0)
{
t_result[t_len] = 96;
}

//加上进位
t_result[t_len] += temp;
temp = 0;

if (t_result[t_len]>=106)
{//如果结果达到进位,置进位标志,并将结果复位
t_result[t_len] -= 10;
temp = 1;
}

//填写最终结果
t_result[t_len] -= 48;
t_len--,slen--,flen--;
}
char* p = t_result;
while (*p++=='0')
{
}
_result = --p;

delete []t_result;

return 0;
}

int CBigInt::pure_sub(const char* _first,const char* _second,std::string& _result)
{
int flen = strlen(_first);
int slen = strlen(_second);

int temp = 0;

int t_len = flen>slen ? flen : slen;
//动态分配存储结果数组,因为是减法,所以结果最大长度为最长操作数长度
//另加上一个结束符号位
char* t_result = new char[t_len+1];
if (t_result==NULL)
{
return -1;
}
memset(t_result,0,t_len+1);

flen--,slen--,t_len--;
while (t_len >= 0)
{
if (slen<0)
{//如果减数循环完
t_result[t_len] = _first[flen]-48;
}
else
{
t_result[t_len] = _first[flen] - _second[slen];
}

//加上进位
t_result[t_len] -= temp;
temp = 0;

if (t_result[t_len]<0)
{//如果结果达到进位,置进位标志,并将结果复位
t_result[t_len] = 10 + t_result[t_len];
temp = 1;
}

//填写最终结果
t_result[t_len] += 48;
t_len--,slen--,flen--;
}

char* p = t_result;
while (*p++=='0')
{
}
_result = --p;

delete []t_result;

return 0;
}

int CBigInt::pure_div(const char* _first,const char* _second,std::string& _result)
{
int flen = strlen(_first);
int slen = strlen(_second);

char s_buf[3] = {0};
int t_pos = 0;
int s_pos = 0;
std::string t_first = _first;
std::string t_result = "";

while (this->abscmp(t_first.c_str(),_second)==-1)
{
t_first += "0";
t_pos++;
}

int t_flen = 0;
char flag = 0;
int i,j = 1;
bool t_flag = false;
while (1)
{
i = 1;
if (t_pos + j > MAX_FLAX_LEN+1)
{
break;
}
while (this->abscmp(t_first.c_str(),_second)==-1)
{
t_first += "0";
if(this->abscmp(t_first.c_str(),_second)==-1&&flag)
{
_result += "0";
j++;
}
if (!flag&&!t_pos)
{
_result += ".";
if(this->abscmp(t_first.c_str(),_second)==-1)
{
_result += "0";
j++;
}
flag = 1;
}
}
t_flen = t_first.length();
while (1)
{
t_result = "";
this->mul(_second,itoa(i++,s_buf,10),t_result);
int rel = this->abscmp(t_result.c_str(),t_first.c_str());
if( rel == -1)
{
t_result = "";
continue;
}
else if (rel == 0)
{
t_flag = true;
break;
}
else
{
t_result="";
this->mul(_second,itoa(i-2,s_buf,10),t_result);
int t_len = t_result.length();
while (t_len+1<t_flen)
{
t_result+="0";
t_len++;
}
while (t_len>t_flen)
{
t_first+="0";
t_len--;
}
this->sub(t_first.c_str(),t_result.c_str(),t_first);

break;
}
}

_result += s_buf[0];

if (t_flag)
{
break;
}
j++;
}

if (t_pos!=0)
{
t_result = "0.";
while (--t_pos>0)
{
t_result += "0";
}
_result = t_result + _result;
}
return 0;
}

int CBigInt::pure_mod(const char* _first,const char* _second,std::string& _result)
{
std::string t_result = "";
std::string s_result = "1";

int i = 0;
while (1)
{
t_result = "";
this->mul(_second,s_result.c_str(),t_result);
int rel = this->abscmp(t_result.c_str(),_first);
i++;
if( rel == -1)
{
t_result = "";
this->add(s_result.c_str(),"1",s_result);
continue;
}
else if (rel == 0)
{
_result = "0";
break;
}
else
{
t_result = "";
this->sub(s_result.c_str(),"1",s_result);
this->mul(_second,s_result.c_str(),t_result);
this->sub(_first,t_result.c_str(),_result);
break;
}
}

return 0;
}

int CBigInt::mul_single(const char* _first,const char _second,std::string& _result)
{
_result = "";
int t_len = strlen(_first);
char* s_result = new char[t_len+2];
memset(s_result,0,t_len+2);

int i = 0,j=0;
while (t_len-->=0)
{
s_result[0] = ((_first[t_len] - 48) * (_second - 48)/10)+48;
s_result[1] = ((_first[t_len] - 48) * (_second - 48)%10)+48;
while (j!=0)
{
s_result[j--+1]='0';
}
i++,j=i;
this->add(_result.c_str(),s_result,_result);
}

delete [] s_result;
return 0;
}

int CBigInt::get_pure(const char* _first,const char* _second)
{
int flen = strlen(_first);
int slen = strlen(_second);

if (flen>slen)
{
return 1;
}
else if (flen<slen)
{
return 2;
}
else
{
int i = 0;
while (i<flen)
{
if (_first[i]>_second[i])
{
return 1;
}
else if (_first[i]<_second[i])
{
return 2;
}
i++;
}
}
return 0;
}

int CBigInt::get_sigh(const char* _first,const char* _second)
{
int t_sigh = 0;

int func_rel = check(_first);
if (func_rel == -1)
{
return -1;
}
else if (func_rel==1)
{
t_sigh += 1;
}

func_rel = check(_second);
if (func_rel == -1)
{
return -1;
}
else if (func_rel==1)
{
t_sigh += 2;
}
return t_sigh;
}

int CBigInt::check(const char* _num)
{
char t_flag = 0;
if (*_num=='-')
{//剔除符号
_num+=1;
t_flag = 1;
}

size_t len = strlen(_num);

//该字符串过大,检测失败
if (len>MAX_NUM_LEN)
{
return -1;
}

int i = 0;
while (*_num!=0)
{//如果字符串中有不是数字的字符或没有结束符
if(*_num>'9'||*_num++<'0'||i++>=len)
{
return -1;
}
}

return t_flag ? 1 : 0;
}

int CBigInt::abscmp(const char* _first,const char* _second)
{
if (*_first == '-')
{
return this->abscmp(_first+1,_second);
}

if (*_second == '-')
{
return this->abscmp(_first,_second+1);
}
int flen = strlen(_first);
int slen = strlen(_second);
if (flen>slen)
{
return 1;
}
else if (flen<slen)
{
return -1;
}
else
{
int i = 0;
while (i<flen)
{
if (_first[i]>_second[i])
{
return 1;
}
else if (_first[i]<_second[i])
{
return -1;
}
i++;
}
}
return 0;
}

int CBigInt::absncmp(const char* _first,const char* _second,int _n)
{
if (*_first == '-')
{
return this->absncmp(_first+1,_second,_n);
}

if (*_second == '-')
{
return this->absncmp(_first,_second+1,_n);
}
int flen = strlen(_first);
int slen = strlen(_second);

char* t_first = new char[flen+1];
char* t_secend = new char[slen+1];
memset(t_first,0,flen+1);
memset(t_secend,0,slen+1);
strncpy(t_first,_first,_n);
strncpy(t_secend,_second,_n);

int rel = this->abscmp(t_first,t_secend);

delete [] t_first;
delete [] t_secend;

return rel;
}

int CBigInt::set_max_f(int _len)
{
m_max_len = _len;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: