大数据运算

来源:互联网 发布:java帮助文档下载 编辑:程序博客网 时间:2024/05/30 23:04
1、大数的数据类型设计    可以用一个string和一个long long类型来表示一个大数类型,long long类型表示没有超出范围,string表示超出范围的大数。在初始化的时候我们可以将string和long 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;}
5、除法的实现 
除法的实现有些复杂,原理如下图所示: 
这里写图片描述
BigData BigData::operator/(BigData b){       if ("+0" == b._strData)        //除数不为0       {              cout << "exception" << endl;              return BigData("");       }        //考虑一些特殊情况       if (!isINIT64overflow(_strData) && !isINIT64overflow(b._strData))       {              return _value / b._value;       }       if ("+0" == _strData || _strData.size()<b._strData.size() || \              (_strData.size()==b._strData.size() && strncmp(_strData.c_str()+1,b._strData.c_str()+1,_strData.size()-1)<0))              return BigData(0);       if (_strData.size() == b._strData.size() && strncmp(_strData.c_str() + 1, b._strData.c_str() + 1, _strData.size() - 1)==0)       {              if (_strData[0]==b._strData[0])                     return BigData(1);              else                     return BigData(-1);       }       if ("+1" == b._strData)              return BigData(_strData);       else if ("-1" == b._strData)       {              string ret= _strData;              ret[0] = '+';              if ('+' == _strData[0])                     ret[0] = '-';              return BigData(ret);       }       return BigData(Div(_strData,b._strData));}string BigData::Div(string strLeft, string strRight){       char symbol = '+';       if (strLeft[0] != strRight[0])              symbol = '-';       size_t LSize = strLeft.size();       size_t RSize = strRight.size();       char *pLeft = (char*)strLeft.c_str()+1;       char *pRight = (char*)strRight.c_str()+1;       size_t dataLen =0;       string strTemp;       strTemp.append(1,symbol);       while ('\0'!=(*(pLeft+dataLen-1)))       {              if ('0' == *pLeft)              {                     pLeft++;                     strTemp.append(1, '0');                     continue;              }              if (!isLgtR(pLeft, dataLen, pRight, RSize-1))              {                     strTemp.append(1,'0');                     dataLen++;              }              else              {                     strTemp.append (1,SubLoop(pLeft, dataLen, pRight, RSize)+'0');                     dataLen++;              }       }       return strTemp;}char BigData::SubLoop(char* &pLeft, size_t& dataLen, const char *pRight,const size_t RSize){       char count = 0;       while (isLgtR(pLeft, dataLen, pRight, RSize-1))       {              for (size_t index = 1; index <= dataLen; index++)              {                     char ret = *(pLeft + dataLen - index) - '0';                     if (RSize>index)                     {                           ret -= (*(pRight + RSize - index-1) - '0');                     }                     if (ret < 0)                     {                           *(pLeft + dataLen - index - 1) -= 1;                           ret += 10;                     }                     *(pLeft + dataLen - index) = ret + '0';              }              count++;              while ('0' == *pLeft&&dataLen>0)              {                     pLeft++;                     dataLen--;              }       }       return count;}//判断以pLeft开始dataLen长度所表示的数的大小是不是大于除数bool BigData::isLgtR(const char* pLeft,const size_t dataLen, const char *pRight, const size_t RSize)  {       if (dataLen > RSize)              return true;       else if (dataLen == RSize)       {              if (strncmp(pLeft, pRight, dataLen) >= 0)                     return true;       }       return false;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110


原创粉丝点击