项目:大数的运算

项目背景:数据的范围超过long long等整型类型所能存储的范围。
项目简介:实现大数的输入和输出以及对它进行加、减、乘和除运算。
开发平台:Visual Studio 2012
技术要点:C++类和对象,string
代码实现:

//CalOfBigData.h

#pragma once

#include <string>
#include <iostream>
#include <cassert>
using namespace std;

#define UN_INIT 0xcccccccccccccccc
#define MAX_INT64 0x7fffffffffffffff
#define MIN_INT64 0x8000000000000000

typedef long long INT64;

int index = 0;

class BigData
{
public:
    BigData(INT64 data = UN_INIT);
    BigData(const char *pData);

    BigData operator+(BigData& bigData);
    BigData operator-(const BigData& bigData);
    BigData operator*(const BigData& bigData);
    BigData operator/(const BigData& bigData);

    friend std::ostream& operator<<(std::ostream& _cout, const BigData& bigData);
    friend std::istream& operator>>(std::istream& _cin, BigData bigData);
    bool IsINT64Overflow()const;

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);
    void INT64ToString();
    bool IsLeftStrBig(char *pLeft, size_t LSize, char *pRight, size_t RSize);
    char SubLoop(char *&pLeft, int& LSize, char *pRight, size_t RSize);
private:
    INT64 Data;
    std::string strData; 
};

//CalOfBigData.cpp 

#include "BigData.h"

BigData::BigData(INT64 data)
: Data(data)
, strData("")
{
    INT64ToString();
}

BigData::BigData(const char *_pdata)
{
    assert(_pdata);
    char csymbol = _pdata[0];
    char* pdata = (char*)_pdata;
    if (csymbol == '+' || csymbol == '-')
    {
        pdata++;
    }
    else if (*pdata >= '0'&& *pdata <= '9')
    {
        csymbol = '+';
    }
    else
    {
        Data = 0;
        strData = '0';
        return;
    }
    while (*pdata == '0')
    {
        pdata++;
    }
    strData.resize(strlen(pdata) + 1);
    Data = 0;
    strData[0] = csymbol;
    int count = 1;
    while (pdata)
    {
        if (*pdata >= '0' && *pdata <= '9')
        {
            Data = Data * 10 + *pdata - '0';
            strData[count++] = *pdata++;
        }
        else
        {
            break;
        }
    }

    if ('-' == csymbol)
    {
        Data = 0 - Data;
    }
}

BigData BigData::operator+(BigData& bigData)
{
    if (!IsINT64Overflow() && !bigData.IsINT64Overflow())
    {
        if (strData[0] != bigData.strData[0])
        {
            return BigData(Data + bigData.Data);
        }
        else
        {
            if ((strData[0] == '+' && MAX_INT64 - Data >= bigData.Data
                || (strData[0]) == '-' && MIN_INT64 - Data <= bigData.Data))
            {
                return BigData(Data + bigData.Data);
            }
        }
    }
    std::string strret; 
    if (strData[0] == bigData.strData[0])
    {
        strret = Add(strData, bigData.strData);
    }
    else
    {
        strret = Sub(strData, bigData.strData);
    }
    return BigData(strret.c_str());
}

BigData BigData::operator-(const BigData& bigData)
{
    if (!IsINT64Overflow() && !bigData.IsINT64Overflow())
    {
        if (strData[0] == bigData.strData[0])
        {
            return BigData(Data - bigData.Data);
        }
        else
        {   
            if ((strData[0] == '+' && MAX_INT64 + bigData.Data>= Data)
                || (strData[0] == '-' && MIN_INT64 + bigData.Data <= Data))
            {
                return BigData(Data - bigData.Data);
            }
        }
    }
    std::string strret;
    if (strData[0] != bigData.strData[0])
    {
        strret = Add(strData, bigData.strData);
    }
    else
    {
        strret = Sub(strData, bigData.strData);
    }
    return BigData(strret.c_str());
}

BigData BigData::operator*(const BigData& bigData)
{
    if (Data == 0 || bigData.Data == 0)
    {
        return BigData(INT64(0));
    }
    if (!IsINT64Overflow() && !bigData.IsINT64Overflow())
    {
        if (strData[0] == bigData.strData[0])
        {
            if ((strData[0] == '+' && MAX_INT64 / Data >= bigData.Data)
                || (strData[0] == '-' && MAX_INT64 / Data <= bigData.Data))
            {
                return BigData(Data * bigData.Data);
            }
        }
        else
        {
            if ((strData[0] == '+' && MIN_INT64 / Data <= bigData.Data)
                || (strData[0] == '-' && MIN_INT64 / Data >= bigData.Data))
            {
                return BigData(Data * bigData.Data);
            }
        }
    }
    return BigData(Mul(strData, bigData.strData).c_str());
}

BigData BigData::operator/(const BigData& bigData)
{
    if (bigData.Data == 0)
    {
        assert("除数不可以为0");
        return BigData(INT64(0));
    }
    if (!IsINT64Overflow() && bigData.IsINT64Overflow())
    {
        return BigData(Data / bigData.Data);
    }
    return BigData(Div(strData, bigData.strData).c_str());
}

std::string BigData::Add(std::string left,std::string right)
{
    int lsize = left.size();
    int rsize = right.size();
    char ch = left[0];
    if (lsize < rsize)
    {
        std::swap(left,right);
        std::swap(lsize,rsize);
    }
    std::string strret;
    strret.resize(lsize + 1);
    strret[0] = ch;
    char cstep = 0;
    int n = 1;
    while (n < lsize)
    {
        char cret = left[lsize - n] - '0' + cstep;
        if (n < rsize)
        {
            cret += right[rsize - n] - '0';
        }
        strret[lsize - n + 1] = (cret % 10 + '0');
        cstep = cret / 10;
        n++;
    }
    strret[1] = cstep + '0';

    return strret;
}

std::string BigData::Sub(std::string left, std::string right)
{
    int lsize = left.size();
    int rsize = right.size();
    char csymbol = left[0];
    if ((lsize < rsize) ||
        (lsize == rsize && left < right))
    {
        std::swap(left, right);
        std::swap(lsize, rsize);
        if (csymbol == '+')
        {
            csymbol = '-';
        }
        else
        {
            csymbol = '+';
        }
    }
    std::string strret;
    strret.resize(lsize);
    strret[0] = csymbol;
    int n = 1;
    while (n < lsize)
    {
        char cret = left[lsize - n] - '0';
        if (n < rsize)
        {
            cret -= right[rsize - n] - '0';
        }
        if (cret < 0)
        {
            left[lsize - n - 1] -= 1;
            cret += 10;
        }
        strret[lsize - n] = (cret + '0');
        n++;
    }
    return strret;
}

std::string BigData::Mul(std::string left, std::string right)
{
    int lsize = left.size();
    int rsize = right.size();
    if (lsize > rsize)
    {
        swap(left, right);
        swap(lsize, rsize);
    }
    char csymbol = '+';
    if (left[0] != right[0])
    {
        csymbol = '-';
    }
    string strret;
    strret.assign(lsize + rsize - 1, '0');
    strret[0] = csymbol;
    int datalen = strret.size();
    int ioffset = 0;
    for (int lidx = 1; lidx < lsize; lidx++)
    {
        char cleft = left[lsize - lidx] - '0';
        char cstep = 0;
        if (cleft == 0)
        {
            ioffset++;
            continue;
        }
        for (int ridx = 1; ridx < rsize; ridx++)
        {
            char cret = cleft*(right[rsize - ridx]-'0');
            cret += cstep;
            cret += (strret[datalen - ioffset - ridx] - '0');
            strret[datalen - ioffset - ridx] = (cret % 10 + '0');
            cstep = cret / 10;
        } 
        strret[datalen - ioffset - rsize] += cstep;
        ioffset++;
    }
    return strret;
}

std::string BigData::Div(std::string left, std::string right)
{
    char lsize = left.size();
    char rsize = right.size();
    char csymbol = '+';
    if (left[0] != right[0])
    {
        csymbol = '-';
    }
    if ((lsize < rsize) || 
        (lsize == rsize && strcmp(left.c_str() + 1, right.c_str() + 1) < 0))
    {
        return "0";
    }
    else
    {
        if (right == "-1" || right == "+1")
        {
            left[0] = csymbol;
            return left;
        }
    }
    string strret;
    strret.append(1, csymbol);
    char *pleft = (char*)(left.c_str() + 1);
    char *pright = (char*)(right.c_str() + 1);
    int datalen = 1;
    lsize -= 1;
    for (index = 0; index< lsize;)
    {
        if (*pleft == '0')
        {
            strret.append(1, '0');
            pleft++;
            index++;
            continue;
        }
        if (!IsLeftStrBig(pleft, datalen, pright, rsize - 1))
        {
            strret.append(1, '0');
            datalen++;
            if (index + datalen > lsize)
            {
                break;
            }
            continue;
        }  
        else
        {
            strret.append(1,SubLoop(pleft, datalen, pright ,rsize - 1));
            datalen++;
        }
    }
    return strret;
}

void BigData::INT64ToString()
{
    char csymbol = '+';
    INT64 tmp = Data;
    if (tmp < 0)
    {
        csymbol = '-';
        tmp = 0 - tmp;
    }
    strData.append(1, csymbol);

    while (tmp)
    {  
        strData.append(1,tmp%10 + '0');
        tmp /= 10;
    }
    char *left = (char*)(strData.c_str() + 1);
    char *right = (char*)(strData.c_str() + strData.size() - 1);
    while (left < right)
    {
        char ctmp = *left;
        *left++ = *right;
        *right-- = ctmp;
    }
}

bool BigData::IsINT64Overflow()const 
{
    std::string tmp;
    if ('+' == strData[0])
    {
        tmp = "+9223372036854775807";
    }
    else
    {
        tmp = "-9223372036854775808";
    }
    if ((strData.size() > tmp.size()) ||
        ((strData.size() == tmp.size())&&(strData > tmp)))
    {
        return true;
    }

    return false;
}

bool BigData::IsLeftStrBig(char *pLeft, size_t LSize, char *pRight, size_t RSize)
{
    assert(pLeft != NULL && pRight != NULL);
    if ((LSize > RSize) ||(LSize == RSize && strncmp(pLeft,pRight,LSize) >= 0))
    {
        return true;
    }
    return false;
}

char BigData::SubLoop(char *&pLeft, int& LSize, char *pRight, size_t RSize)
{
    assert(pLeft != NULL && pRight != NULL);
    char cret = '0';
    while (true)
    {
        if (!IsLeftStrBig(pLeft, LSize, pRight, RSize))
        {
            break;
        }
        int ldatalen = LSize - 1;
        int rdatalen = RSize - 1;
        while (ldatalen >= 0 && rdatalen >= 0)
        {
            if (pLeft[ldatalen] < pRight[rdatalen])
            {
                pLeft[ldatalen - 1] -= 1;
                pLeft[ldatalen] += 10;
            }
            pLeft[ldatalen] = pLeft[ldatalen] - pRight[rdatalen] + '0';
            ldatalen--;
            rdatalen--;
        }
        while ((*pLeft == '0') && (LSize > 0))
        {
            pLeft++;
            LSize--;
            index++;
        }
        cret++;
    }
    return cret;
}

std::ostream& operator<<(std::ostream& _cout, const BigData& bigData)
{
    if (!bigData.IsINT64Overflow()) 
    {
        _cout << bigData.Data;
    }
    else
    {
        char* pData = (char*)bigData.strData.c_str();
        if (pData[0] == '+')
        {
            pData++;
        }
        _cout << pData;
    }
    return _cout;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值