大数运算

来源:互联网 发布:淘宝网密码登录不了 编辑:程序博客网 时间:2024/06/16 20:06
1、大数的数据类型设计    可以用一个string和一个long long类型来表示一个大数类型,long long类型表示没有超出范围,string表示超出范围的大数。在初始化的时候我们可以将stringlong long都进行初始化,在运算的时候再判断是用long long运算还是用string进行运算。typedef long long INIT64;class BigData{       friend ostream& operator<<(ostream& os,const BigData& b);public:       BigData(INIT64  value=0);       BigData(string strData);       BigData operator+(BigData b);       BigData operator-(BigData b);       BigData operator*(BigData b);       BigData operator/(BigData b);private:       bool isINIT64overflow(const string& strData);       string Add(string strLeft, string strRight);       string Sub(string strLeft, string strRight);       string Mul(string strLeft, string strRight);       string Div(string strLeft, string strRight);       char SubLoop(char* &pLeft, size_t& dataLen, const char *pRight, const size_t RSize);       bool isLgtR(const char* pLeft, const size_t dataLen, const char *pRight, const size_t RSize);private:       INIT64 _value;       string _strData;};1.1、用一个整数初始化大数对象,其中sprintf的作用就相当于itoa.BigData::BigData(INIT64  value)       :_value(value){       char buf[128] = { 0 };       sprintf(buf,"%lld",_value);       _strData =buf;}1.2、用一个字符串初始化一个大数对象,考虑到输入的字符串可能有各种异常情况,比如前面一空白字符或0开头,出现字母等等,我们将常见的异常情况过滤掉(可以参考atoi是怎么进行过滤的)。BigData::BigData(string strData)       :_value(0)       , _strData("+0"){       char* pData = (char*)strData.c_str();       while (isspace(*pData))              //过滤空白              pData++;       if ('\0' == *pData)              return;       char symbol = *pData;       if (('+' == *pData) || ('-' == *pData))    //过滤符号              pData++;       else if (isdigit(*pData))              symbol = '+';       else              return;       while('0' == *pData)         //过滤前面的0              pData++;       if ('\0' == *pData)              return;       _strData.resize(strlen(pData)+1);       _strData[0] = symbol;       int count = 1;       while (*pData>='0' && *pData<='9')       {              _value = _value * 10 + *pData - '0';              _strData[count++] = *pData;              pData++;       }       if (*pData)              _strData.resize(count);       if (symbol == '-')              _value = 0 - _value;}1.3、判断一个大数是不是超出范围,因为整数的最大数据类型是long long类型,我们必须用string中的值进行判断,判断大数是不是超出范围。bool BigData::isINIT64overflow(const string& strData){       const string max_value= "+9223372036854775807";       const string min_value= "-9223372036854775808";       if (strData.size() < max_value.size())              return false;       else if (strData.size() == max_value.size())       {              if (('+'==strData[0]&&strData<=max_value)\                     ||('-'==strData[0]&&strData>=min_value))                     return false;       }       return true;}ostream& operator<<(ostream& os, const BigData& b){       const char *str = b._strData.c_str();       if ('+' == *str)              cout << str + 1;       else              cout << str;       return os;}2、加法的实现BigData BigData::operator+(BigData b){       if (!isINIT64overflow(_strData) && !isINIT64overflow(b._strData))   //如果都没溢出       {              if (_strData[0] != b._strData[0])     //异号直接相加,不会溢出                     return _value + b._value;              else if ('+' == _strData[0] && '+' == b._strData[0])              {                     INIT64 max_value = 9223372036854775807;                     if (max_value - _value >= b._value)       //两个正数相加不会溢出                     {                           return _value + b._value;                     }              }              else if ('-' == _strData[0] && '-' == b._strData[0])              {                     INIT64 min_value =0-9223372036854775808;                     if (min_value - _value <= b._value)   //两个负数相加不会溢出                     {                           return _value + b._value;                     }              }       }       if (_strData[0] == b._strData[0])      //同号相加              return BigData(Add(_strData, b._strData));       else                                         //异号相加可以转换成减法       {               //异号相加转换成正号相减              string Left = _strData;                     string Right = b._strData;              Left[0] = '+';              Right[0] = '+';              if ('-' == _strData[0])                            swap(Left,Right);              return BigData(Sub(Left,Right));       }}string BigData::Add(string strLeft,string strRight){       size_t LSize = strLeft.size();       size_t RSize = strRight.size();       if (LSize < RSize)                 //为了方便,我们保证+号左边的数的位数不小于加号右边的数       {              swap(strLeft,strRight);              swap(LSize,RSize);       }       string strTemp;       strTemp.resize(LSize+1);                 //两个数相加,结果的位数最长是两个运算数中位数最长的运算数加+1       strTemp[0] = strLeft[0];                       char step = 0;                            //记录进位       for (size_t index = 1; index < LSize;index++)       {              char ret = strLeft[LSize - index]-'0';              ret += step;              if (RSize>index)              {                     ret=ret+strRight[RSize-index] - '0';              }              step = ret / 10;                     //保存进位情况              strTemp[LSize + 1 - index] = ret%10+'0';        }       strTemp[1] = step+'0';                   //向最高位进位,取决于step的值       return strTemp;}3、减法的实现参考加法4、乘法的实现BigData BigData::operator * (BigData b){       if ("+0" == _strData || "+0" == b._strData)              return BigData(0);       if (!isINIT64overflow(_strData) && !isINIT64overflow(b._strData))       {              INIT64 max_value = 9223372036854775807;              INIT64 min_value = 0 - 9223372036854775808;              if (_strData[0] == b._strData[0])              {                     if (('+' == _strData[0] && max_value / _value >= b._value) || \                           ('-' == _strData[0] && max_value / _value <= b._value))                           return _value*b._value;              }              else              {                     if (('+' == _strData[0] && min_value / _value <= b._value) || \                           ('-' == _strData[0] && min_value / _value >= b._value))                           return BigData(_value*b._value);              }       }       //判断运算数中有没有为正负1的特殊情况       if ("+1"==_strData)              return BigData(b._strData);       if ("+1" == b._strData)              return BigData(_strData);       if ("-1" == _strData)       {              string ret = b._strData;              if ('+' == b._strData[0])                     ret[0] = '-';              else                     ret[0] = '+';              return BigData(ret);       }       if ("-1" == b._strData)       {              string ret =_strData;              if ('+' ==_strData[0])                     ret[0] = '-';              else                     ret[0] = '+';              return BigData(ret);       }       return BigData(Mul(_strData, b._strData));}string BigData::Mul(string strLeft, string strRight){       size_t LSize = strLeft.size();       size_t RSize = strRight.size();       //乘法相乘的时候,保证*号左边的数的长度小于等于*号右边的数       if(LSize > RSize)       {              swap(LSize,RSize);              swap(strLeft,strRight);       }       char symbol = '+';       if (strLeft[0] != strRight[0])         //异号相乘为负              symbol='-';       string strTemp;       strTemp.resize(LSize+RSize-1,'0');      //两数相乘,结果的位数最长是两个运算数位数之和       strTemp[0] = symbol;       //因为两个数相乘,即乘数的每一位都要和被乘数相运算,所以必须用两个循环       for (size_t i = 1; i < LSize;i++)       {              if ('0' == strLeft[LSize - i])                     continue;              char step=0;                         //记录进位              for (size_t j=1;j<RSize;j++)              {                     char ret = strLeft[LSize-i]-'0';                     ret*=(strRight[RSize-j]-'0');                     ret += step+strTemp[LSize + RSize - j - i] - '0';                     strTemp[LSize + RSize - j - i]= ret%10+'0';                     step = ret / 10;              }              strTemp[LSize- i] += step;       }       return strTemp;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高中的会考没过怎么办 毕业证和学位证丢了怎么办 大学毕业证学位证丢了怎么办 大学毕业证和学位证丢了怎么办 毕业证是士官证号码怎么办 自考本科准考证丢了怎么办 自考档案搞丢了怎么办 自考本科档案在自己手里怎么办? 本科自考准考证丢了怎么办 大学团员证丢了怎么办 大学开学团员证丢了怎么办 研究生开学没有团员证怎么办 研究生开学已经不是团员了怎么办 毕业了要搬宿舍怎么办 中专学历认证已停止怎么办 中专不做学历认证考试怎么办 大学生欠学费被扣毕业证怎么办 考警校体检没过怎么办 美国签证申请预约名字写错怎么办 当兵不从学校走怎么办 门牙崩了一小块怎么办 遇到很难过的事情怎么办 小孩子上课精力不集中怎么办 每天工作都很累压力大怎么办 重体力活搬不动怎么办 大学没参加体测怎么办 英文写的很丑怎么办 患有勃起障碍应该怎么办较好 运动过度小腿肌肉酸痛怎么办 高考有纹身是字怎么办 新生儿测听力没过关怎么办 色弱高考体检时没查出来怎么办 公司福利体检查二对半怎么办 高考体检表复印件丢了怎么办 高考体检表身高填错了怎么办 大学档案高考体检表丢了怎么办 工厂组织体检我有乙肝怎么办 我有乙肝单位组织体检怎么办? 矮腰袜子老掉怎么办 短腰袜子老下滑怎么办 中考体检结果丢了怎么办