您的位置:首页 > 大数据

大数项目:用字符串表示超过内存表示范围的大数据并实现四则运算

2016-07-15 22:44 585 查看
原理很简单,直接上代码。

这里是初级版,效率低下,代码复杂不明了。只是尽可能的实现功能,改进版将在后续推出。

这里是头文件 BigData.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

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

typedef long long INT_64;
#define   MAX_INT_64 0x7fffffffffffffff
#define   MIN_INT_64 -9223372036854775807

INT_64 Stoll(const std::string &s1);
std::string onlynum(const std::string &str);

void MulAdd(std::string& tmp, int RIdx);

class BigData
{
public:
BigData(INT_64 value = 0);

BigData(std::string &str);

BigData(const char* a);

friend std::ostream& operator<<(std::ostream&os, const BigData&bigdata);
BigData& operator=(const BigData&bigdata);
bool _IsINT64Overflow()const;
BigData operator+(const BigData&bigdata);
BigData operator-(const BigData&bigdata);
BigData operator*(const BigData&bigdata);
BigData operator/(const BigData&bigdata);

int DivSub(std::string& tmp, std::string& pRight);
bool IsLessThanDiv(std::string& pRight, std::string& tmp);

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);

private:
INT_64 _value;
std::string _strData;
};


BigData.cpp

#include"BigData.h"
using namespace std;

BigData::BigData(INT_64 value)
:_value(value)
{
int count = 0;
INT_64 tmp = _value;
while (tmp)
{
count++;
tmp /= 10;
}

int size = count + 1;
_strData.resize(size);
if (_value >= 0)
{
_strData[0] = '+';
tmp = _value;
}
else
{
_strData[0] = '-';
tmp = -_value;
}

char cRet = 0;
while (tmp)
{
cRet = tmp % 10 + '0';
tmp /= 10;
_strData[count--] = cRet;
}

}

bool BigData::_IsINT64Overflow() const
{
if (_strData.size()<20)
{
return false;
}
if (_strData.size() == 20)
{
char* str="9223372036854775807";
int ret=_strData.compare(1, 19, str);
if (ret <= 0)
{
return false;
}
}
return true;
}

BigData::BigData(std::string &str)
:_value(0)
{
str=onlynum(str);
if ((str[0] != '-') && (str[0] != '+'))
{
_strData = "+";
_strData = _strData + str;
}
else
{
_strData = _strData + str;
}

if (!_IsINT64Overflow())
{
_value = Stoll(_strData);
}
}

BigData::BigData(const char* a)
{
assert(a);
char cSymbol = a[0];

if (a[0] <= '9'&&a[0] >= '0')
{
cSymbol = '+';
}
else if (a[0] == '+' || a[0] == '-')
{
a++;
}
else
{
_value = 0;
return;
}

while (*a == '0')
{
a++;
}

_strData.resize(strlen(a) + 1);
_strData[0] = cSymbol;

int iCount = 1;
_value = 0;
while (*a >= '0'&& *a <= '9')
{
_strData[iCount++] = *a;
_value = _value * 10 + *a - '0';
a++;
}

if (cSymbol == '-')
{
_value = 0 - _value;
}

_strData.resize(iCount);
}

ostream& operator<<(ostream&os, const BigData&bigdata)
{
if (bigdata._strData == "")
{
os << bigdata._value;
}
if (!bigdata._IsINT64Overflow())
{
os << bigdata._value;
}
else
{
char* pData = (char*)bigdata._strData.c_str();//
os << pData;
}
return os;
}

BigData& BigData::operator=(const BigData&bigdata)
{
_value = bigdata._value;
_strData = bigdata._strData;
return *this;
}

INT_64 Stoll(const string &s1)
{
char cSymbol = s1[0];
int icount = 0;
if (cSymbol >= '0' && cSymbol <= '9')
{
cSymbol = '+';
}
else if ('+' == cSymbol || '-' == cSymbol)
{
++icount;
}
else
{
return 0;
}

while ('0' == s1[icount])
{
++icount;
}

INT_64 _ret = 0;
while (s1[icount] >= '0' && s1[icount] <= '9')
{
_ret = _ret * 10 + (s1[icount]) - '0';
icount++;
}

if ('-' == cSymbol)
{
_ret = 0 - _ret;
}

return _ret;
}

string onlynum(const string &str)
{
string ret=str;
if (ret == "")
{
ret = "+0";
return ret;
}
int iCount = 0;
int idx = 0;
while (' ' == ret[idx])
{
++idx;
}

char cSymbol = ret[idx];
if ('+' == cSymbol || '-' == cSymbol)
{
iCount++;
}
else
{
if (cSymbol > '0' || cSymbol <= '9')
{
cSymbol = '+';
}
}

while ('0' == ret[iCount + idx])
{
++idx;
}

while (ret[iCount + idx] >= '0' && ret[iCount + idx] <= '9')
{
++iCount;
}
ret.erase(1, idx);
ret.resize(iCount);
return ret;
}

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_INT_64 - _value >= bigData._value) ||
('-' == _strData[0] && MIN_INT_64 - _value <= bigData._value))
{
return BigData(_value + bigData._value);
}
}
}
//超出
if (_strData[0] == bigData._strData[0])
{
return BigData(Add(_strData, bigData._strData));
}

return BigData(Sub(_strData, bigData._strData));
}

std::string BigData::Add(std::string left, std::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, '0');
strRet[0] = left[0];

//逐位相加
int cstep = 0;
for (int iIdx = 1; iIdx < Lsize; iIdx++)
{
int cRet = left[Lsize - iIdx] - '0' + cstep;
if (iIdx < Rsize)
{
cRet += right[Rsize - iIdx] - '0';
}

strRet[Lsize - iIdx + 1] = cRet % 10 + '0';
cstep = cRet / 10;
}

strRet[1] = cstep + '0';

return strRet;
}

string BigData::Sub(std::string left, std::string right)
{
char* pleft = (char *)left.c_str();
char* pright = (char *)right.c_str();

int Lsize = left.size();
int Rsize = right.size();

string strRet;
strRet.resize(Lsize);
if (Lsize == Rsize)
{
if ((strcmp(pleft+1, pright+1) >= 0 && left[0] == '+') ||
(strcmp(pleft+1, pright+1) < 0 && left[0] == '-'))
{
strRet[0] = '+';
}
else
{
strRet[0] = '-';
}
}

if (Lsize < Rsize)
{
if (left[0] == '-')
{
strRet[0] = '+';
}
else
{
strRet[0] = '-';
}
swap(left, right);
swap(Lsize, Rsize);
strRet.resize(Lsize);
}

if (Lsize > Rsize)
{
strRet[0] = left[0];
}
//逐位相减
for (int iIdx = 1; iIdx < Lsize; iIdx++)
{
int cRet = left[Lsize - iIdx] - '0';
if (iIdx < Rsize)
{
cRet -= right[Rsize - iIdx] - '0';
}
if (cRet < 0)
{
cRet += 10;
left[Lsize - iIdx - 1] -= 1;
}
strRet[Lsize - iIdx] = cRet + '0';
}
return strRet;
}

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_INT_64 + bigData._value >= _value) ||
('-' == _strData[0] && MIN_INT_64 + bigData._value <= _value))
{
return BigData(_value - bigData._value);
}
}
}

// 超出
if (_strData[0] != bigData._strData[0])
{

std::string strRet = Add(_strData, bigData._strData);
strRet[0] = _strData[0];

return BigData(strRet);
}

return BigData(Sub(_strData, bigData._strData));
}

BigData BigData::operator*(const BigData& bigData)
{
//两个数都没有溢出
if (!_IsINT64Overflow() && !bigData._IsINT64Overflow())
{
//同号相乘不会溢出
if (_strData[0] == bigData._strData[0])
{
if ((_strData[0] == '+'&&MAX_INT_64 / _value >= bigData._value) ||
(_strData[0] == '-'&&MAX_INT_64 / _value <= bigData._value))
{
return (_value * bigData._value);
}
}

//异号相乘不会溢出
else
{
if ((_strData[0] == '-'&&MIN_INT_64 / _value >= bigData._value) ||
(_strData[0] == '+'&&MIN_INT_64 / _value <= bigData._value))
{
return (_value * bigData._value);
}
}
}

//至少有一个溢出或者相乘结果溢出
return (BigData(Mul(_strData, bigData._strData)));
}

string BigData::Mul(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 + Rsize - 1, '0');
strRet[0] = '+';

//逐位相乘
int cstep = 0;
string tmp;
tmp.resize(Lsize + 1, '0');
string Inistring(tmp);
for (int RIdx = 1; RIdx < Rsize; RIdx++)
{
for (int LIdx = 1; LIdx < Lsize; LIdx++)
{
int cRet = right[Rsize - RIdx] - '0';
cRet *= left[Lsize - LIdx] - '0';

cRet += cstep;
//if (cRet>=10)
//{
cstep = cRet / 10;
cRet = cRet % 10;
//}
tmp[Lsize - LIdx + 1] = cRet + '0';
}

tmp[1] = cstep + '0';
tmp[0] = '+';
tmp.append(RIdx-1, '0');

strRet = (BigData(tmp)+ BigData(strRet))._strData;//相加结果保存在strRet中
tmp = Inistring;
cstep = 0;
}

if (left[0] != right[0])
strRet[0] = '-';
return strRet;
}

BigData BigData::operator/(const BigData& bigData)
{
return BigData(Div(_strData, bigData._strData));
assert(!(bigData._value == 0 && _strData == "+"));
BigData b("0");

//被除数为零
if (_value == 0&&_strData=="+")
{
return b;
}

if ((!_IsINT64Overflow())&& (!bigData._IsINT64Overflow()))
{
return _value / bigData._value;
}

if (_strData.size() < bigData._strData.size())
{
return b;
}
else if (_strData.size() == bigData._strData.size())
{
if (strcmp((char*)_strData.c_str() + 1, (char*)bigData._strData.c_str() + 1) < 0)
{
return b;
}
else if (strcmp((char*)_strData.c_str() + 1, (char*)bigData._strData.c_str() + 1) == 0)
{
if (_strData[0] == bigData._strData[0])
{
return BigData(1);
}
else
return BigData(-1);
}
else
{
INT_64 ret = 0;
ret = DivSub(_strData, (string)bigData._strData);
return BigData(ret)._strData;
}
}
else
return BigData(Div(_strData, bigData._strData));
}

bool BigData::IsLessThanDiv(string& tmp,string& Right)
{
BigData ret = BigData(tmp.c_str() + 1) - BigData(Right.c_str() + 1);
if (ret._strData[0] == '-')
return true;
return false;
}

int BigData::DivSub(string& tmp, string& pRight)
{
int count = 0;
char cRet = 0;
while (!IsLessThanDiv(tmp, pRight))
{
count++;
tmp = Sub(tmp, pRight);
}

return count;
}

string BigData::Div(string left, string right)
{
string strRet;
strRet.resize(1);

if (left[0] != right[0])
{
strRet[0] = '-';
}
else
strRet[0] = '+';

string tmp;
tmp.resize(right.size(), '0');
int iIdx = 0;
for (iIdx = 0; iIdx < right.size(); iIdx++)
{
tmp[iIdx] = left[iIdx];
}

int count = 0;
//此时iIdx=right,size();
while (iIdx < left.size())
{
//不能减,再取一位
if (IsLessThanDiv(tmp, right))
{
strRet.append(1, '0');
tmp.append(1, left[iIdx++]);
continue;
}
//能除,确定商
count = DivSub(tmp, right);
char c = count + '0';
strRet.append(1, c);
tmp.append(1, left[iIdx++]);
}
//将余下的tmp计算一次
count = DivSub(tmp, right);
char c = count + '0';
strRet.append(1, c);

return strRet;
}


最后是一组简单的测试函数

#include"BigData.h"

using namespace std;

void funtest1()
{
string s1 =      "000009223372036854775808";
string s2 =    "10";
BigData bd1(s1);
cout << bd1 << endl;
BigData bd2(10);
cout << bd2 << endl;
BigData bd3 = bd1 + bd2;
cout << bd3 << endl;
}

void funtest2()
{
string s1 ="+3333666666666667777777777777333";
string s2 ="+999999999999999999999999999999";

BigData bd1(s1);
cout << bd1 << endl;
BigData bd2(s2);
cout << bd2 << endl;
BigData bd3 = bd1 - bd2;
cout << bd3 << endl;
}

void funtest3()
{
string s1 = "-999999999999999999999999";
string s2 = "-222222222222222222222";
BigData bd1(s1);
cout << bd1 << endl;
BigData bd2(s2);
cout << bd2 << endl;
BigData bd3 = bd1 * bd2;
cout << bd3 << endl;
}

void funtest4()
{
string s1 = "-990000000000000000099";
string s2 = "33";
//-30303030303030303030303030303030303
//-3030303030303030303030303030303030
BigData bd1(s1);
cout << bd1 << endl;
BigData bd2(s2);
cout << bd2 << endl;
BigData bd3 = bd1 / bd2;
cout << bd3 << endl;
}

int main()
{
//funtest1();
//funtest2();
//funtest3();
funtest4();

system("pause");
return 0;
}


代码逻辑都很简单,只是写起来比较费事,所以如此冗长。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: