計算機中整數數據的最大類型爲long long
類型,依據計算機位數的不同它的範圍也不同,以32位爲例long long
類型的取值範圍爲【-9223372036854775808,9223372036854775807】,那麼計算機可以進行的數值運算就必須在這個範圍之內嗎?未必,所以產生了大數據運算來解決更大範圍內的數值運算,它的思想是以字符串代表數值進行各類運算。
Test.c
#include"BigData.h"
int main()
{
BigData bg1(9900000099);
BigData bg2(33);
BigData bg3;
bg3 = bg1 - bg2;
cout << bg3 << endl;
return 0;
}
BigData.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<assert.h>
#include<ctype.h>
using namespace std;
typedef long long INT64;
const INT64 MAX_VALUE = 9223372036854775807;
const INT64 MIN_VALUE = -9223372036854775808;
class BigData
{
public:
BigData(INT64 value = 0);
BigData(const string& str);
BigData operator+(const BigData& bg) const;
BigData operator-(BigData bg) const;
BigData operator*(const BigData& bg) const;
BigData operator/(const BigData& bg) const;
friend ostream& operator<<(ostream& cou,const BigData& bg);
bool IsINT64OverFlow() const;
private:
string _strData;
INT64 _value;
};
BigData.cpp
#include"BigData.h"
BigData::BigData(INT64 value)//用數值初始化對象的構造函數
: _value(value)
{
char Symbol = '+';
if (value < 0)
Symbol = '-';
do
{
_strData += (value % 10) + '0';
value /= 10;
}
while (value);
_strData += Symbol;
char* ptr = (char*)_strData.c_str();
reverse(ptr, ptr + _strData.size());//逆置字符串
}
BigData::BigData(const string& str)//用字符串初始化對象的構造函數
:_strData("+0")
, _value(0)
{
char* ptr = (char*)str.c_str();
while (isspace(*ptr))//排除空白字符串
{
ptr++;
}
if (*ptr == '\0')
return;
char Symbol = 0;
if (*ptr == '+' || *ptr == '-')
{
Symbol = *ptr;
ptr++;
}
else if (isdigit(*ptr))
{
Symbol = '+';
}
else
return;
while (*ptr == '0')//排除數字最開始處的零
*ptr++;
if (*ptr == '\0')
return;
_strData[0] = Symbol;
int count = 1;
_strData.resize(strlen(ptr) + 1);
while (isdigit(*ptr))
{
_strData[count] = *ptr;
_value = _value*10 + (*ptr - '0');
count++;
ptr++;
}
if (_strData[0] == '-')
_value = -_value;
}
bool BigData::IsINT64OverFlow() const//判斷對象中的_value是否超出long long類型的範圍
{
string strRet("+9223372036854775807");
if (_strData[0] == '-')
strRet = "-9223372036854775808";
if ((strRet.size() > _strData.size()) || (_strData.size() == strRet.size() && strcmp(_strData.c_str(), strRet.c_str()) <= 0))
return false;
return true;
}
string Add(string strLeft, string strRight)//同號加法
{
string strRet;
size_t LSize = strLeft.size();
size_t RSize = strRight.size();
if (LSize < RSize)//將左參數調整爲最長字符串
{
strLeft.swap(strRet);
swap(LSize, RSize);
}
strRet.resize(LSize + 1);//結果字符串最長長度
strRet[0] = strLeft[0];
char Step = 0;//進位
for (size_t i = 1; i < LSize; i++)
{
char Ret = (strLeft[LSize - i] - '0') + Step;
if (i < RSize)
Ret += strRight[RSize - i] - '0';
if (Ret >= 10)
{
Step = Ret / 10;
Ret = Ret % 10;
}
strRet[LSize - i + 1] = Ret + '0';
}
strRet[1] = Step + '0';
return strRet;
}
string Sub(string strLeft, string strRight)//異號加法
{
size_t LSize = strLeft.size();
size_t RSize = strRight.size();
string strRet;//調整左字符串爲長度最長或字符串最大的字符(不含符號位)
if (LSize < RSize || (LSize == RSize && strcmp(strLeft.c_str() + 1, strRight.c_str() + 1) < 0))
{
strLeft.swap(strRight);
swap(LSize, RSize);
}
strRet.resize(LSize);
strRet[0] = strLeft[0];
for (size_t i = 1; i < LSize; i++)
{
char Ret = (strLeft[LSize - i] - '0');
if (i < RSize)
Ret -= strRight[RSize - i] - '0';
if (Ret < 0)
{
strRet[LSize - i - 1] -= 1;
Ret += 10;
}
strRet[LSize - i] = Ret + '0';
}
return strRet;
}
string Mul(string strLeft, string strRight)//乘法
{
string strRet;
size_t LSize = strLeft.size();
size_t RSize = strRight.size();
if (LSize > RSize)
{
strLeft.swap(strRight);
swap(LSize, RSize);
}
strRet.resize(LSize + RSize - 1, '0');
if (strLeft[0] == strRight[0])
strRet[0] = '+';
else
strRet[0] = '-';
char offset = 0;
for (size_t i = 1; i < LSize; i++)
{
char Step = 0;
char Ret = strLeft[LSize - i] - '0';//左字符串的從右往左每一位
for (size_t j = 1; j < RSize; j++)//用左字符串取出的一位位乘右字符串的每一位
{
char Res = Ret*(strRight[RSize - j] - '0') + Step
+ (strRet[LSize + RSize - 1 - j - offset] - '0');
Step = 0;
if (Res > 10)
{
Step = Res / 10;
}
strRet[LSize + RSize - 1 - j - offset] = (Res % 10) + '0';
}
strRet[LSize - offset - 1] = Step + '0';
offset++;
}
return strRet;
}
bool IsLeftBig(char* pLeft,size_t DataLen,char* pRight,size_t RSize)
//判斷除法中每一次進入SubLoop函數中的左參數字符串是否大於右參數字符串
{
if (DataLen > RSize ||
(DataLen == RSize && strcmp(pLeft, pRight) >= 0))
return true;
return false;
}
char SubLoop(char*& pLeft, size_t& DataLen, char*& pRight, size_t& RSize)
//除法中的減法
{
char Com = '0';//循環次數 == 商數
while (1)
{
while (*pLeft == '0' && DataLen > 0)//最多跳過DataLen個0
{
pLeft++;
DataLen--;
}
if (!IsLeftBig(pLeft, DataLen, pRight, RSize))
break;
for (size_t i = 1; i <= RSize; i++)//一次減法
{
char Ret = pLeft[DataLen - i] - '0';
Ret -= pRight[RSize - i] - '0';
if (Ret < 0)
{
pLeft[DataLen - i - 1] -= 1;
Ret += 10;
}
pLeft[DataLen - i] = Ret + '0';
}
Com++;
}
return Com;
}
string Div(string strLeft, string strRight)//除法
{
string strRet;
char* pLeft = (char*)(strLeft.c_str() + 1);
char* pRight = (char*)(strRight.c_str() + 1);
size_t LSize = strLeft.size();
size_t RSize = strRight.size() - 1;
size_t DataLen = RSize;
if (strLeft[0] == strRight[0])
strRet += '+';
else
strRet += '-';
while (strRet.size() < (LSize - RSize + 1))
{
if (*pLeft == '0')//如果下一位爲零,則商零
{
strRet += '0';
pLeft++;
continue;
}
if (!IsLeftBig(pLeft,DataLen,pRight,RSize))
{
strRet += '0';
DataLen++;
strRet += SubLoop(pLeft, DataLen, pRight, RSize);
}
else
{
strRet += SubLoop(pLeft, DataLen, pRight, RSize);
}
DataLen++;
}
return strRet;
}
BigData BigData::operator+(const BigData& bg) const
{
if (!IsINT64OverFlow() && !bg.IsINT64OverFlow())
{
if (_strData[0] != bg._strData[0])
{
return BigData(_value + bg._value);
}
else if ((_strData[0] == '+' && (MAX_VALUE - _value >= bg._value))
|| (_strData[0] == '-' && (MIN_VALUE - _value <= bg._value)))
{
return BigData(_value + bg._value);
}
}
if (_strData[0] == bg._strData[0])
return BigData(Add(_strData, bg._strData));
return BigData(Sub(_strData, bg._strData));
}
BigData BigData::operator-(BigData bg) const
{
if (!IsINT64OverFlow() && !bg.IsINT64OverFlow())
{
if (_strData[0] == bg._strData[0])
{
return BigData(_value - bg._value);
}
else if ((_strData[0] == '+' && MAX_VALUE + bg._value >= _value)
|| (_strData[0] == '-' && MIN_VALUE + bg._value <= _value))
{
return BigData(_value - bg._value);
}
}
if (_strData[0] == bg._strData[0])
{
if (_strData[0] == '+')
bg._strData[0] = '-';
else
bg._strData[0] = '+';
return BigData(Sub(_strData,bg._strData));
}
else
{
if (_strData[0] == '+')
bg._strData[0] = '+';
else
bg._strData[0] = '-';
return BigData(Add(_strData,bg._strData));
}
}
BigData BigData::operator*(const BigData& bg) const
{
if (_strData == "+0" || bg._strData == "+0")
return BigData(0);
if (!IsINT64OverFlow() && !bg.IsINT64OverFlow())
{
if (_strData[0] == bg._strData[0])
{
if ((_strData[0] == '+' && MAX_VALUE / _value >= bg._value)
|| (_strData[0] == '-' && MAX_VALUE / _value <= bg._value))
{
return BigData(_value * bg._value);
}
}
else
{
if ((_strData[0] == '+' && MIN_VALUE / _value <= bg._value)
|| (_strData[0] == '-' && MIN_VALUE / _value >= bg._value))
{
return BigData(_value * bg._value);
}
}
}
return BigData(Mul(_strData, bg._strData));
}
BigData BigData::operator/(const BigData& bg) const
{
//除數爲0
if (bg._strData == "+0")
{
assert(0);
}
if (_strData == "+0")
return BigData(0);
//左邊小於右邊
if ((_strData.size() < bg._strData.size())
|| ((_strData.size() == bg._strData.size())
&& strcmp(_strData.c_str() + 1, bg._strData.c_str() + 1) < 0))
return BigData(0);
if ((_strData.size() == bg._strData.size())
&& strcmp(_strData.c_str() + 1, bg._strData.c_str() + 1) == 0)
{
if (_strData[0] == bg._strData[0])
return BigData(1);
else
return BigData(-1);
}
if (bg._strData == "+1" || bg._strData == "-1")
{
BigData tmp(*this);
if (_strData[0] == bg._strData[0])
{
tmp._strData[0] = '+';
}
else
{
tmp._strData[0] = '-';
}
return tmp;
}
if (!IsINT64OverFlow() && !bg.IsINT64OverFlow())
return BigData(_value / bg._value);
return BigData(Div(_strData, bg._strData));
}
ostream& operator<<(ostream& cou,const BigData& bg)
{
cou << "string:" << bg._strData << " value:" << bg._value;
return cou;
}