《C++大数据运算(+、-、*、)》

xiaoxiao2021-02-28  291

计算机中整数数据的最大类型为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; }
转载请注明原文地址: https://www.6miu.com/read-23682.html

最新回复(0)