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

来源:互联网 发布:java格式化html代码 编辑:程序博客网 时间:2024/05/06 04:34

原理很简单,直接上代码。
这里是初级版,效率低下,代码复杂不明了。只是尽可能的实现功能,改进版将在后续推出。
这里是头文件 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 -9223372036854775807INT_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;}

代码逻辑都很简单,只是写起来比较费事,所以如此冗长。

1 0
原创粉丝点击