WAY?
为什么会有大数据运算?缘由?
在c++中常用的数据类型有 char:1 bit,short 2 bit,int 4 bit,long long 8 bit等等,以上数据类型标识的数据大小非常有限,如果遇到大于他们能表示的范围时,计算结果就会有误,日常生活中的计算器也是如此,我国计算两个比较大的数的运算,也会出现错误,或者不能正常显示,
例如计算123456789123456789*987654321987654321
计算结果如下:
具体区别如下:
分析:
在数据运算中会出现两种情况:一种是数据、且小计算结果不会溢出;另一种是数据溢出或者计算结果会溢出;
所以为了计算便捷,也为了节省运算量,我设置了如下两种储存数据方式,并且在计算也分情况不同而选择不同方法,形式如下:
做了什么?
为了解决上述问题,我写了一个计算大数据四则运算以及求模的小项目,实现的功能有 + - * / %;
主要的接口以及实现代码如下:
程序头文件以及接口如下:
/*
*
* 项目名称:大数据运算
* 接口名称:BigData.h
* 作 者: 邹明
* 完成时间:2016.04.12
*
*/
#ifndef __BIG_DATA_H__
#define __BIG_DATA_H__
#include<iostream>
using namespace std;
#include<string.h>
#include<assert.h>
#define MAX_INT64 0x7FFFFFFFFFFFFFFF //小数据能表示的最大值
#define MIN_INT64 0x8000000000000000 //小数据能表示的最小值
#define INIT 0xcccccccccccccccc
typedef long long INT64;
class BigData
{
public:
BigData(INT64 value= INIT);
BigData(const char*ptrData);
//运算符重载
BigData operator+(const BigData& bigdata);
BigData operator-(const BigData& bigdata);
BigData operator*(const BigData& bigdata);
BigData operator/(const BigData& bigdata);
BigData operator%(const BigData& bigdata);
private:
std::string Add(std::string left, std::string right);
std::string Sub(std::string left, std::string right);
std::string Mul(std::string left, std::string right);
std::string Div(std::string left, std::string right);
std::string Mod(std::string left, std::string right); //求模
bool IsINT64OverFlow() const; //判断是否越界
void INT64ToString(); //数据转化为字符串
bool IsLeftStrBig(const char *pLeft, int LSise, const char *pRight, int RSise); //比较左操作数是否大于有操作数
char SubLoop(char *pLeft, int LSise, const char *pRight, int RSise); //除法时每次求商运算
friend std::ostream&operator<<(std::ostream & cout, const BigData& bigdata); //输出运算符重载
private:
INT64 _value; //整形数据形式
string _strData; //字符串数据形式
};
#endif
实现代码,文件名称BigData.cpp,下面文件晕包含于此内
构造函数,转化字符串,判断越界,输出运算符重载等函数
#include"BigData.h"
BigData::BigData(INT64 value) //小数据构造函数
:_value(value)
{
INT64ToString();
}
BigData::BigData(const char*ptrData)//大数据构造函数
{
//123456 //+1223356 //122334qwer //qwee123 //0000qwer
assert(ptrData);
char *pstr = (char*)ptrData;
char cSymbol = '+';
if (('+' == *pstr) || ('-' == *pstr))
{
cSymbol = *pstr;
pstr++;
}
else if (('0' <= *pstr)&&('9' >= *pstr))
{
cSymbol = '+';
}
else if (*pstr == ' ')
{
while (*pstr == ' ')
{
pstr++;
}
if (('+' == *pstr) || ('-' == *pstr))
{
cSymbol = *pstr;
pstr++;
}
else if (('0' <= *pstr) && ('9' >= *pstr))
{
cSymbol = '+';
}
}
else
{
return;
}
while (' ' == *pstr)
pstr++;
while ('0' == *pstr)
pstr++;
_strData.resize(strlen(ptrData)+1);
_strData[0] = cSymbol;
_value = 0;
int iCount = 1;
while ((*pstr >= '0') && (*pstr <= '9'))
{
_value = _value * 10 + (*pstr - '0');
_strData[iCount] = *pstr;
pstr++;
iCount++;
}
_strData.resize(iCount);
if (cSymbol == '-')
{
_value = 0 - _value;
}
}
void BigData::INT64ToString() //将数据的数值填充至字符串部分
{
char cSymbl = '+';
if (_value < 0)
{
cSymbl = '-';
}
//1234567
//7654321
_strData.append(1, cSymbl);
INT64 temp = _value;
if (temp < 0)
{
temp = 0 - temp;
}
while (temp)
{
_strData.append(1, temp % 10 + '0');
temp /= 10;
}
char *pleft = (char*)_strData.c_str() + 1;
char *pright = pleft + _strData.size() - 2;
while (pleft < pright)
{
char tem = *pleft;
*pleft = *pright;
*pright = tem;
pleft++;
pright--;
}
}
bool BigData::IsINT64OverFlow()const //判断是否越界
{
std::string temp("+9223372036854775807");
if ('-' == _strData[0])
{
temp = "-9223372036854775808";
}
if (_strData.size() < temp.size())
{
return true;
}
else if ((_strData.size() == temp.size()) && (_strData <= temp))
{
return true;
}
return false;
}
//求商
char BigData::SubLoop(char *pLeft, int LSize, const char *pRight, int RSize)
{
assert(pLeft);
assert(pRight);
char cRet = '0';
while (true)
{
while ((*pLeft == '0')&&LSize>0)
{
pLeft++;
LSize--;
}
if (!IsLeftStrBig(pLeft, LSize, pRight, RSize))
{
break;
}
for (int i = 1;i<=LSize; i++)
{
if ((LSize > RSize) && (i == LSize))
{
break;
}
char ret = pLeft[LSize - i];
ret -= pRight[RSize - i];
if (ret < 0)
{
pLeft[LSize - i - 1] -= 1;
ret += 10;
}
pLeft[LSize - i] = ret+'0';
}
cRet++;
}
return cRet;
}
//判断左操作数是否大于右操作数
bool BigData::IsLeftStrBig(const char *pLeft, int LSise, const char *pRight, int RSise)
{
if (LSise > RSise ||
((LSise == RSise) && (strcmp(pLeft, pRight) >= 0)))
{
return true;
}
return false;
}
//输出运算符重载
std::ostream&operator<<(std::ostream & _cout, const BigData& bigdata)
{
if (bigdata.IsINT64OverFlow())
{
_cout << bigdata._value;
}
else
{
char *pData = (char*)bigdata._strData.c_str();
if ('+' == pData[0])
{
pData++;
}
_cout << pData;
}
return _cout;
}
加运算
BigData BigData::operator+(const BigData& bigdata) //+ 加法运算符重载
{
if (IsINT64OverFlow() && bigdata.IsINT64OverFlow())
{
if (_strData[0] != bigdata._strData[0])
{
return BigData(_value + bigdata._value);
}
else
{
INT64 temp_max = MAX_INT64 - _value;
INT64 temp_min = MIN_INT64 - _value;
//10 -3 =7 5
//(-10)-(-3)=-7 -5
if (((_value >= 0) && (temp_max >= bigdata._value)) ||
((_value < 0) && (temp_min <= bigdata._value)))
{
return BigData(_value + bigdata._value);
}
}
}
if (_strData[0] == bigdata._strData[0])
{
return BigData(Add(_strData, bigdata._strData).c_str());
}
else
{
if(_strData[0] == '+')
{
string ptr(bigdata._strData);
ptr[0] = '+';
return Sub(_strData, ptr).c_str();
}
else
{
string ptr(_strData);
ptr[0] = '+';
return Sub(bigdata._strData, ptr).c_str();
}
}
}
std::string BigData::Add(std::string left, std::string right)
{
int iLsize = left.size();
int iRsize = right.size();
char cSymbol = left[0]; //取得符号位
if (iLsize < iRsize)
{
std::swap(left, right);
std::swap(iLsize, iRsize);
}
std::string sRet;
sRet.resize(iLsize + 1);
char Step = 0;
for (int i = 1; i < iLsize; i++)
{
char cRet = left[iLsize - i] - '0' + Step;
if (i < iRsize)
{
cRet += (right[iRsize - i] - '0');
}
sRet[iLsize - i + 1] = cRet % 10 + '0';
Step = cRet / 10;
}
sRet[1] = Step + '0';
sRet[0]=cSymbol;
return sRet;
}
减运算:
BigData BigData::operator-(const BigData& bigdata) //- 减法运算符重载
{
if (IsINT64OverFlow() && bigdata.IsINT64OverFlow())
{
if (_strData[0] == bigdata._strData[0])
{
return BigData(_value - bigdata._value);
}
else
{
INT64 temp_max = _value - MAX_INT64;
INT64 temp_min = _value - MIN_INT64;
//10 -3 =7 5
//(-10)-(-3)=-7 -5
if (((_value >= 0) && (temp_max <= bigdata._value)) ||
((_value < 0) && (temp_min >= bigdata._value)))
{
return BigData(_value - bigdata._value);
}
}
}
if (_strData[0] == bigdata._strData[0])
{
return BigData(Sub(_strData, bigdata._strData).c_str());
}
else
{
string ptr(bigdata._strData);
ptr[0] = _strData[0];
return Add(_strData, ptr).c_str();
}
}
std::string BigData::Sub(std::string left, std::string right)
{
int iLsize = left.size();
int iRsize = right.size();
int Max_size = iLsize;
std::string sRet;
char cSymbol = left[0]; //取符号位
if (iLsize <= iRsize)
{
if ((iLsize == iRsize) && (strcmp(left.c_str() ,right.c_str())<0) && (left[0] == right[0]))
{
if ('+' == right[0])
{
cSymbol = '-';
}
else
{
cSymbol = '+';
}
Max_size = iRsize;
std::swap(left, right);
std::swap(iLsize, iRsize);
}
}
else
{
cSymbol = left[0];
Max_size = iLsize;
}
char Step = 0;
sRet.assign(Max_size, 48);
for (int i = 1; i < Max_size; i++)
{
char cRet = 0;
if (0<(iLsize - i))
{
cRet = left[iLsize - i] - '0' + Step;
}
if (i < iRsize)
{
if (cRet < right[iRsize - i] - '0')
{
cRet += 10;
}
Step = 0 - (cRet-Step) / 10;
cRet -= (right[iRsize - i] - '0');
}
sRet[Max_size - i ] = cRet + '0';
}
sRet[0] = cSymbol;
return sRet;
}
乘运算:
BigData BigData::operator*(const BigData& bigdata)
{
if ((0 == _value)||(0==bigdata._value))
{
return BigData(INT64(0));
}
if (IsINT64OverFlow() && bigdata.IsINT64OverFlow())
{
if (_strData[0] == bigdata._strData[0])
{
if (((_value > 0) && ((long long)MAX_INT64 / _value >= bigdata._value)) ||
((_value < 0) && ((long long)MAX_INT64 / _value <= bigdata._value))) //同号相乘 结果为正
{
return BigData(_value*bigdata._value);
}
}
else
{
if (((_value > 0) && ((long long)MIN_INT64 / _value <= bigdata._value)) ||
((_value < 0) && ((long long)MIN_INT64 / _value >= bigdata._value))) //异号相乘 结果为负
{
return BigData(_value*bigdata._value);
}
}
}
return BigData(Mul(_strData, bigdata._strData).c_str());
}
std::string BigData::Mul(std::string left, std::string right)
{
char cSymbol = '+'; //设置符号位
int iLsize = left.size();
int iRsize = right.size();
if (left[0] == right[0])
cSymbol = '+';
else
cSymbol = '-';
if (iLsize > iRsize)
{
std::swap(left, right);
std::swap(iLsize, iRsize);
}
std::string sRet;
int t = 1;
if (((left[1] - '0')*(right[1] - '0') +(left[1] - '0')*(right[1] - '0')%10)<10)
{
t = 2;
}
else
t = 1;
//sRet.resize(iLsize + iRsize - t);
sRet.assign(iLsize + iRsize - t,'0');
int sizeRet = iLsize + iRsize - 1;
sRet[0] = cSymbol;
int i = 1, j = 1;
for (i = 1, j = 1; i < iLsize; i++)
{
char step = 0;
char cleft = left[iLsize - i] - '0';
for (int j = 1; j < iRsize; j++)
{
char cRet = cleft*(right[iRsize - j] - '0') + step + (sRet[sizeRet - i - j + 1] - '0');
step = cRet / 10;
sRet[sizeRet - i - j + 1] = cRet%10 + '0';
if ((j+1)==iRsize)
sRet[sizeRet - i - j] = step+'0';
}
}
return sRet;
}
除运算:
BigData BigData::operator/(const BigData& bigdata)
{
if (bigdata._strData[1] == '0')
{
cout << "除数为 0 " << endl;
assert(0);
}
if (_strData[1] == 0)
return INT64(0);
if ((IsINT64OverFlow()) && bigdata.IsINT64OverFlow())
{
return _value / bigdata._value;
}
if (_strData.size() < bigdata._strData.size())
{
return INT64(0);
}
else if (_strData.size() == bigdata._strData.size())
{
if (strcmp(_strData.c_str() + 1, bigdata._strData.c_str() + 1) < 0)
return INT64(0);
if (strcmp(_strData.c_str() + 1, bigdata._strData.c_str() + 1) == 0)
{
if (_strData[0] == bigdata._strData[0])
return INT64(1);
else
return INT64(-1);
}
}
return BigData(Div(_strData, bigdata._strData).c_str());
}
std::string BigData::Div(std::string left, std::string right)
{
string sRet;
sRet.append(1, '+');
if (left[0] != right[0])
{
sRet[0] = '-';
}
char *pLeft = (char *)(left.c_str() + 1);
char *pRight = (char *)(right.c_str() + 1);
int DataLen = right.size() - 1;
int Lsize = left.size() - 1;
for (int i = 0; i < Lsize; i++)
{
if (!IsLeftStrBig(pLeft, DataLen, pRight, right.size()-1))
{
sRet.append(1, '0');
DataLen++;
}
else
{
sRet.append(1, SubLoop(pLeft, DataLen, pRight, right.size() - 1));
}
if (DataLen + i>Lsize)
{
break;
}
if (*pLeft == '0')
{
pLeft++;
}
else
{
DataLen = right.size();
}
}
return sRet;
}
摸除运算:
BigData BigData:: operator%(const BigData& bigdata)
{
if (bigdata._strData[1] == '0')
{
cout << "除数为 0 或对0求模" << endl;
assert(0);
}
if (_strData[1] == 0)
return INT64(0);
if ((IsINT64OverFlow()) && bigdata.IsINT64OverFlow())
{
return _value % bigdata._value;
}
if (_strData.size() < bigdata._strData.size())
{
return BigData(_strData.c_str());
}
else if (_strData.size() == bigdata._strData.size())
{
if (strcmp(_strData.c_str() + 1, bigdata._strData.c_str() + 1) < 0)
return INT64(0);
if (strcmp(_strData.c_str() + 1, bigdata._strData.c_str() + 1) == 0)
{
return INT64(0);
}
}
return BigData(Mod(_strData, bigdata._strData).c_str());
}
std::string BigData::Mod(std::string left, std::string right)
{
char cSymbol = left[0];
BigData n1(left.c_str() + 1);
BigData n2(right.c_str() + 1);
BigData n3 = n1 / n2;
BigData n4 = n3*n2;
BigData sRet(n1 - n4);
sRet._strData[0] = cSymbol;
return sRet._strData;
}
测试用例,文件名test.cpp
#include"BigData.h"
void Test1()
{
BigData n1(123456);
BigData b2("12346678");
BigData b3("+12346678");
BigData b4("-123466");
BigData b5("+");
BigData b6(" ");
BigData b7("12346aaaa");
BigData b8("+asd12346678");
BigData b9("000012346678");
cout << "n1:" << n1 << endl;
cout << "b2:" << b2 << endl;
cout << "b3:" << b3 << endl;
cout << "b4:" << b4 << endl;
cout << "b5:" << b5 << endl;
cout << "b6:" << b6 << endl;
cout << "b7:" << b7 << endl;
cout << "b8:" << b8 << endl;
cout << "b9:" << b9 << endl;
}
void testAdd()
{
BigData b1("-45353");
BigData b2("37353753");
BigData b3("- 9223372036854775808");
BigData b4(" 9223372036854775800");
BigData b5(" -9223372036854775810");
BigData b6("9223372036854775900");
//1、都在INT64范围内
cout << (b1 + b1) << endl;
cout << (b2 + b2) << endl;
cout << (b1 + b2) << endl;
cout << "b4:" << b4 << endl;
cout << (b1 + b4) << endl;
cout << b3 << endl;
cout << (b1 + b3) << endl;
cout << (b2 + b4) << endl;
//2、都不在INT64范围内
cout << (b2 + b5) << endl;
cout << (b1 + b6) << endl;
cout << (b6 + b1) << endl;
}
void testSub()
{
BigData b1("-45353");
BigData b2("37353753");
BigData b3("-9223372036854775808");
BigData b4("9223372036854775800");
BigData b5("-9223372036854775810");
BigData b6("9223372036854775900");
//1、都在INT64范围内
cout << (b1 - b2) << endl;
cout << (b2 - b1) << endl;
cout << (b3 - b1) << endl;
cout << (b1 - b4) << endl;
cout << (b3 - b2) << endl;
cout << (b4 - b1) << endl;
cout << (b1 - b3) << endl;
cout << (b2 - b4) << endl;
cout << endl;
//2、一个在一个不在<运算后在范围内,运算后不在范围内>
cout << (b5 - b1) << endl;
cout << (b1 - b5) << endl;
cout << endl;
cout << (b6 - b2) << endl;
cout << (b2 - b6) << endl;
cout << endl;
cout << (b6 - b5) << endl;
cout << (b5 - b6) << endl;
cout << (b2 - b5) << endl;
cout << (b1 - b6) << endl;
cout << (b6 - b1) << endl;
}
void testMul()
{
BigData b1("-45353");
BigData b2("37353753");
BigData b3("-9223372036854775808");
BigData b4(" 9223372036854775800");
BigData b5("-9223372036854775810");
BigData b6(" 9223372036854775900");
//1、都在INT64范围内
cout << (BigData("999") * BigData("22222222222222222222222222222")) << endl;
cout << (b2 * b1) << endl;
cout << (b1 * b2) << endl;
cout << (b1 * BigData("0")) << endl;
cout << (BigData("0") * b2) << endl;
cout << endl;
cout << (b3 * b1) << endl;
cout << (b1 * b3) << endl;
cout << (b1 * b4) << endl;
cout << (b4 * b1) << endl;
cout << (b3 * b2) << endl;
cout << (b2 * b4) << endl;
cout << endl;
//2、一个在一个不在<运算后在范围内,运算后不在范围内>
cout << (BigData("0") * b6) << endl;
cout << (b5 * BigData("0")) << endl;
cout << (b5 * b1) << endl;
cout << (b1* b5) << endl;
cout << endl;
cout << (b6 * b2) << endl;
cout << (b2 * b6) << endl;
cout << endl;
cout << (b6 * b5) << endl;
cout << (b5 * b6) << endl;
cout << (b2 * b5) << endl;
cout << endl;
cout << (b1 * b6) << endl;
cout << (b6 * b1) << endl;
}
void testDiv()
{
BigData b1("-45353");
BigData b2("37353753");
BigData b3("-9223372036854775808");
BigData b4(" 9223372036854775800");
BigData b5("-9223372036854775810");
BigData b6(" 9223372036854775900");
BigData b7("-1231123203367738338252");
//1、排除除数为0
cout << (b1 / BigData(0)) << endl;
//2、在范围内
cout << (b1 / b2) << endl;
cout << (b2 / b1) << endl;
//3、不在范围内<左(被除数)比右(除数)小为0,左比右大>
cout << (b2 / b5) << endl;
cout << (b2 / b6) << endl;
cout << (b5 / b2) << endl;
cout << (b6 / b2) << endl;
cout << (b6 / b1) << endl;
cout << (b5 / b1) << endl;
cout << b7 / b1 << endl;
}
void testMod()
{
BigData b1("-45353");
BigData b2("37353753");
BigData b3("-9223372036854775808");
BigData b4(" 9223372036854775800");
BigData b5("-9223372036854775810");
BigData b6(" 9223372036854775900");
BigData b7("-1231123203367738338252");
//1、排除除数为0
cout << (b1 / BigData(0)) << endl;
//2、在范围内
cout << (b1 % b2) << endl;
cout << (b2 % b1) << endl;
//3、不在范围内
cout << (b2 % b5) << endl;
cout << (b2 % b6) << endl;
cout << (b5 % b2) << endl;
cout << (b6 % b2) << endl;
cout << (b6 % b1) << endl;
cout << (b5 % b1) << endl;
cout << b7 % b1 << endl;
}
int main()
{
//testAdd(); //测试+
//testSub(); //测试-
//testMul(); //测试 *
//testDiv(); //测试 /
testMod(); //测试%
system("pause");
return 0;
}
运行结果:
加运算:
减运算:
乘运算:
除运算:
模除运算:
以上代码均为原创,实现了与小数据运算同样的功能,如果发现错误,欢迎各位读者批评指正,谢谢
本文出自 “分享中进步” 博客,请务必保留此出处http://xmwen1.blog.51cto.com/10730069/1763620