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

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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值