大数据的存储及运算

来源:互联网 发布:node js前景 知乎 编辑:程序博客网 时间:2024/05/20 05:56

      在计算机中,每种类型都有自己的表示范围,比如int (0x80000000,0x7FFFFFFF),那如果超过范围之后呢?它就是一个无意义的数,可是有时我们就需要存储一些很大的数据,那怎么办呢?

      我们可以把数据放到字符串中。


所以,我们需要实现一种新的数据类型,使它内置类型操作上没有影响,同时又可以支持大数据的四则运算,并且操作效率要尽可能的高。

 初始化:

   空大数

   整数构造大数

   字符串构造大数

为了方便运算,我们把大数的第一位设置成符号位,正号+,负号-。

   可能传的值:

   “1234567890”

   “+123456790”

   “-1234567890”

   “123abc4567890”

   “+00001234567890”

 构造大数:

BigData::BigData(INT64 value)
    : _value(value)
{}
BigData::BigData(char * pData)
{
assert(NULL != pData);
char cSymbol = pData[0]; // 符号标志位


if (pData[0] >= '0'&&pData[0] <= '9')//第一位是数字
{
cSymbol = '+';
}
else if (cSymbol == '+' || cSymbol == '-')//第一位是正负号
{
pData++;
}
else
{
_value = UN_INIT;// 第一位不是正负号也不是数字直接返回一个随机值
return;
}
while (*pData == '0')
{
pData++;
}
//转化数据
_strData.resize(strlen(pData) + 1);
_strData[0] = cSymbol;


// 保存数据
int icount = 1;
_value = 0;//给他初始值
while (*pData >= '0'&&*pData <= '9')
{
_strData[icount++] = *pData;
_value = _value * 10 + *pData - '0';
pData++;
}
if (cSymbol == '-')
{
_value = _value;
}


_strData.resize(icount);
}


bool BigData::IsINT64Overflow()const//修饰this
{
string temp("+9223372036854775807");
if (_strData[0] == '-')
{
temp = ("-9223372036854775808");
}
//比较
if (_strData.size() < temp.size())
{
return false;
}
else if (_strData.size() == temp.size() && _strData <= temp)
{
return false;
}
return true;
}
ostream& operator<<(ostream& _cout, const BigData& bigData)
{
if (!bigData.IsINT64Overflow())
{
      _cout << bigData._value;
}
else
{
char *pData =(char*) bigData._strData.c_str();
if (bigData._strData[0] == '+')
{
pData++;
}
_cout << pData;
}
return _cout;
}




加法:

1,如果相加的结果没有超出内置类型

  相加不会溢出:同号 异号

 相加会溢出:同号 同为正号 或同为负号

2,结果超出内置类型

  同号

  异号(调用减法)

溢出



不溢出



减法:

若两个数据都没有溢出:

1,同号 直接相减

2,异号 得数有可能溢出


至少有一个超出,或者结果超出

Sub


乘法:

结果没有溢出 直接相乘:

同号

异号

至少有一个溢出||结果超出

Mul


除法:

1,如果都没有超出,直接除

right!=0;

left=0;结果为零

left<right;结果为零

left=right绝对值相等;结果为正负一

right=+-1;结果为正负left

2,超出

Div

整体代码

bigData.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"BigData.h"
#include<assert.h>


BigData::BigData(INT64 value)
    : _value(value)
, _strData("")
{
INT64ToString();
}
BigData::BigData(char * pData)
{
assert(NULL != pData);
char cSymbol = pData[0]; // 符号标志位


if (pData[0] >= '0'&&pData[0] <= '9')//第一位是数字
{
cSymbol = '+';
}
else if (cSymbol == '+' || cSymbol == '-')//第一位是正负号
{
pData++;
}
else
{
_value = UN_INIT;// 第一位不是正负号也不是数字直接返回一个随机值
return;
}
while (*pData == '0')
{
pData++;
}
//转化数据
_strData.resize(strlen(pData) + 1);
_strData[0] = cSymbol;


// 保存数据
int icount = 1;
_value = 0;//给他初始值
while (*pData >= '0'&&*pData <= '9')
{
_strData[icount++] = *pData;
_value = _value * 10 + *pData - '0';
pData++;
}
if (cSymbol == '-')
{
_value = 0-_value;
}


_strData.resize(icount);
}


BigData BigData::operator+(const BigData& bigData)
{
if (!IsINT64Overflow() && !bigData.IsINT64Overflow())
{
if (_strData[0] != bigData._strData[0])
{
return BigData(_value + bigData._value);
}
else
{
if (((_strData[0] == '+')&&(MAX_INT64 - _value >= bigData._value)) ||
(('-' == _strData[0] )&&( MIN_INT64 - _value <= bigData._value)))
{
return BigData(_value + bigData._value);
}
else
{
return BigData((char*)Add(_strData, bigData._strData).c_str());
}
}
}
//操作数溢出
//操作数不溢出,结果溢出
if (_strData[0] == bigData._strData[0])
{
return BigData((char*)Add(_strData, bigData._strData).c_str());
}
return BigData((char*)Sub(_strData, bigData._strData).c_str());
}


BigData BigData::operator-(const BigData& bigData)
{
if (!IsINT64Overflow()&&!bigData.IsINT64Overflow())
{
if (_strData[0] == bigData._strData[0])
{
return BigData(_value - bigData._value);
}
else
{
if ((_strData[0] == '+'&&MAX_INT64 - _value >= bigData._value) ||
('-' == _strData[0] && MAX_INT64) - _value <= bigData._value)
{
return BigData(_value - bigData._value);
}
}
}
if (_strData[0] != bigData._strData[0])
{
return BigData((char*)Add(_strData, bigData._strData).c_str());
}


return BigData((char*)Sub(_strData, bigData._strData).c_str());
}


BigData BigData::operator*(const BigData& bigData)
{
if (_value == 0 || bigData._value == 0)
{
return BigData(INT64(0));
}
if (!IsINT64Overflow() && !bigData.IsINT64Overflow())
{
//同号
if (_strData[0] == bigData._strData[0])
{
if (((_strData[0] == '+') && (MAX_INT64 / _value >= bigData._value)) ||
(('-' == _strData[0]) && (MAX_INT64 / _value <= bigData._value)))
{
return BigData(_value * bigData._value);
}
else
{
return BigData((char*)Mul(_strData, bigData._strData).c_str());
}
}
else
{
      //异号
  if (((_strData[0] == '+')&&( MIN_INT64 / _value <= bigData._value)) ||
  ((_strData[0] == '-')&&( MIN_INT64 / _value >= bigData._value)))
   {
return BigData(_value*bigData._value);
   }
  else
  {
  return BigData((char*)Mul(_strData, bigData._strData).c_str());
  }
}

}
return BigData((char*)Mul(_strData, bigData._strData).c_str());
}
BigData BigData::operator/(const BigData& bigData)
{
if (bigData._value == 0)
{
assert("除数不能为0");
return BigData(INT64(0));
}
if (!IsINT64Overflow() && !bigData.IsINT64Overflow())
{
return BigData(_value / bigData._value);
}
if (_strData.size() < bigData._strData.size() ||
(_strData.size() == bigData._strData.size()&&strcmp(_strData.c_str() + 1, bigData._strData.c_str() + 1) < 0))
{
return BigData(INT64(0));
}
if (bigData._strData == "+1" || _strData == "-1")
{
string ret = _strData;
if (_strData[0] != bigData._strData[0])
{
ret[0] = '-';
}
return BigData((char*)ret.c_str());
}
if (_strData.size() == bigData._strData.size() && strcmp(_strData.c_str() + 1, bigData._strData.c_str() + 1))
{
string ret = "+1";
if (_strData[0] != bigData._strData[0])
{
ret[0] = '-';
}
return BigData((char*)ret.c_str());
}
return BigData((char*)Div(_strData, bigData._strData).c_str());
}
string BigData::Add(string left, string right)
{
//始终保持左边的数大于右边的数
int Lsize = left.size();
int Rsize = right.size();
if (Lsize < Rsize)
{
swap(left, right);
swap(Lsize,Rsize);
}


string strRet;
strRet.resize(Lsize + 1);
strRet[0] = left[0];


//逐位相加
char cStep = 0;


for (int index = 1; index < Lsize; index++)//第0位是符号位
{
char cRet = left[Lsize - index] + cStep - '0';
if (index < Rsize)
{
cRet += right[Rsize - index] - '0';
}
strRet[Lsize - index + 1] = cRet % 10 + '0';
cStep = cRet / 10;
}
strRet[1] = cStep + '0';
return strRet;
}
string BigData::Sub(string left, string right)
{
int Lsize = left.size();
int Rsize = right.size();
char cSymbol = left[0];//符号位
if (Lsize < Rsize || Lsize==Rsize && left<right)
{
swap(left, right);
swap(Lsize, Rsize);

if (left[0] == '+')
{
cSymbol = '-';
}
else
cSymbol = '+';
}


//逐位相减
string strRet;//记录结果
strRet.resize(Lsize);
strRet[0] = cSymbol;
for (int index = 1; index < Lsize; index++)
{
char cRet = left[Lsize - index] - '0';
if (index < Rsize)
{
cRet -= right[Rsize - index] - '0';
}


if (cRet < 0)//借位
{
left[Lsize - index - 1] -= 1;
cRet += 10;
}
strRet[Lsize - index] = cRet + '0';
}
return strRet;
}


string BigData::Mul(string left, string right)
{
int Lsize = left.size();
int Rsize = right.size();
if (Lsize > Rsize)
{
swap(left, right);
swap(Lsize, Rsize);
}
char cSymbol = '+';//左右符号位相同为正
if (left[0] != right[0])//左右符号位不同为负
{
cSymbol = '-';
}
string strRet;
strRet.assign(Lsize+Rsize-1,'0');
strRet[0] = cSymbol;
char cStep = 0;//初始化进位
int DataLen = strRet.size();
int offset = 0;//错位


for (int index = 1; index < Lsize; ++index)
{
char cLeft = left[Lsize - index] - '0';
cStep = 0;
if (cLeft == 0)
{
offset++;
continue;
}
for (int lindex = 1; lindex < Rsize; ++lindex)
{
char cRet = cLeft*(right[Rsize - lindex] - '0');
cRet += strRet[DataLen - lindex - offset] - '0';
cRet += cStep;
cStep = cRet / 10; //进位
strRet[DataLen-lindex-offset] = cRet % 10 + '0';
}
strRet[DataLen - Rsize - offset] += cStep;
offset++;
}
return strRet;
}
string BigData::Div(string left, string right)
{
string strret;
strret.append(1, '+');
if (left[0] != right[0])
{
strret[0] = '-';
}
char *pleft = (char*)(left.c_str() + 1);
char *pright = (char*)(right.c_str() + 1);
int lsize = left.size()-1;
int datalen = right.size() - 1;
for (int idx = 0; idx < lsize;)
{
if (*pleft == '0')
{
strret.append(1, '0');
pleft++;
idx++;
continue;
}
if (!IsLeftBig(pleft, datalen, pright, right.size() - 1))
{
strret.append(1, '0');
datalen++;
if (idx + datalen > lsize)
{
break;
}
}
else
{
strret.append(1, SubLoop(pleft, datalen, pright, right.size() - 1));
while (*pleft == '0' && datalen > 0)
{
pleft++;
idx++;
datalen--;
}
datalen++;
if (datalen + idx > lsize)
{
break;
}
}
}
return strret;
}


void BigData::INT64ToString()
{
char csymbol = '+';
INT64 tmp = _value;
if (tmp < 0)
{
csymbol = '-';
tmp = 0 - tmp;
}
_strData.append(1, csymbol);


while (tmp)
{
_strData.append(1, tmp % 10 + '0');
tmp /= 10;
}
char *left = (char*)(_strData.c_str() + 1);
char *right = (char*)(_strData.c_str() + _strData.size() - 1);
while (left < right)
{
char ctmp = *left;
*left++ = *right;
*right-- = ctmp;
}
}


bool BigData::IsINT64Overflow()const//修饰this
{
string temp("+9223372036854775807");
if (_strData[0] == '-')
{
temp = ("-9223372036854775808");
}
//比较
if (_strData.size() < temp.size())
{
return false;
}
else if (_strData.size() == temp.size() && _strData <= temp)
{
return false;
}
return true;
}


char BigData::SubLoop(char* pLeft, int Lsize, char* pRight, int Rsize)
{
assert(pLeft != NULL&&pRight != NULL);
char cret = '0';
while (true)
{
if (!IsLeftBig(pLeft, Lsize, pRight, Rsize))
{
break;
}
int Ldatalen = Lsize - 1;
int Rdatalen = Rsize - 1;
while (Ldatalen > 0 && Rsize > 0)
{
char ret = pLeft[Ldatalen] - '0';
ret -= pRight[Rdatalen] - '0';
if (ret < 0)
{
pLeft[Ldatalen-1] -= 1;
ret += 10;
}
pLeft[Ldatalen] = ret + '0';
Ldatalen--;
Rdatalen--;
}
while ((*pLeft == '0') && (Lsize > 0))
{
pLeft++;
Lsize--;
}
cret++;
}
return cret;
}


bool BigData::IsLeftBig(char* pLeft, int Lsize, char* pRight, int Rsize)
{
assert(pLeft != NULL && pRight != NULL);
if ((Lsize > Rsize) || (Lsize == Rsize && strncmp(pLeft, pRight,Lsize) >= 0))
{
return true;
}
return false;
}
ostream& operator<<(ostream& _cout, const BigData& bigData)
{
if (!bigData.IsINT64Overflow())
{
      _cout << bigData._value;
}
else
{
char *pData =(char*) bigData._strData.c_str();
if (bigData._strData[0] == '+')
{
pData++;
}
_cout << pData;
}
return _cout;
}

BigData.h

#pragma once 


#include<string>
#include<iostream>
using namespace std;


typedef long long INT64;
#define UN_INIT 0xCCCCCCCCCCCCCCCC
#define MAX_INT64 0X7FFFFFFFFFFFFFFF
#define MIN_INT64 0X8000000000000000


class BigData
{
public:
BigData(INT64 value);
BigData(char* pData);


BigData operator+(const BigData& bigData);
BigData operator-(const BigData& bigData);
BigData operator*(const BigData& bigData);
BigData operator/(const BigData& bigData);


friend ostream& operator<<(ostream& _cout,const BigData& bigData);
private:
string Add(string left, string right);
string Sub(string left, string right);
string Mul(string left, string right);
string Div(string left, string right);


void INT64ToString();
bool IsINT64Overflow()const;//判断是否超过long long 范围
char SubLoop(char* pLeft,int Lsize,char* pRight,int Rsize);
bool IsLeftBig(char* pLeft, int Lsize, char* pRight, int Rsize);
private:
INT64 _value;
string _strData;
};

BigDataTest.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"BigData.h"
#include<stdlib.h>
#include<iostream>
using namespace std;


void FunTeat1()
{
  BigData bigData("-0001223456667880900");
  cout << bigData << endl;
}
void FundTest2()
{
BigData left("9223372036854775808");
BigData right("99");
cout << left / right << endl;
}
int main()
{
//FunTeat1();
FundTest2();
    system("pause");
return 0;
}

0 0
原创粉丝点击