千家信息网

浅析《大数据运算》-加减乘除以及模除运算

发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,WAY?为什么会有大数据运算?缘由?在c++中常用的数据类型有 char:1 bit,short 2 bit,int 4 bit,long long 8 bit等等,以上数据类型标识的数据大小非常有限
千家信息网最后更新 2025年01月24日浅析《大数据运算》-加减乘除以及模除运算


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__#includeusing namespace std;#include#include#define MAX_INT64 0x7FFFFFFFFFFFFFFF  //小数据能表示的最大值#define MIN_INT64 0x8000000000000000   //小数据能表示的最小值#define INIT 0xcccccccccccccccctypedef 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)        {                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 + '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;}

运行结果:

加运算:

减运算:

乘运算:

除运算:

模除运算:

以上代码均为原创,实现了与小数据运算同样的功能,如果发现错误,欢迎各位读者批评指正,谢谢

0