C++项目 - 大数四则运算

大数运算


开发环境:Windows Visual Studio 2013
项目概述:利用String类实现对大数的读写,以及实现大数之间的加、减、乘、除、取模和比较运算。
使用技术:C++、String类。
项目思想:使用C++类将超过C++中能够存储最大整型变量(long long int)所能存储的范围的数转换成字符串进行存储,将存储大数的字符串拆开进行分析,逐位进行运算存储,实现大数间的加、减、乘、除、取模和比较运算。将大数运算分解成单个字符的运算。

Bignum.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include 
#include 
#include 
using namespace std;


#define MAX_INT64 9223372036854775807  
#define MIN_INT64 -9223372036854775808 


typedef long long INT64;

class BigData
{
public:
    BigData(INT64 data); 
    BigData(const char *_pdata);  
    BigData operator+(BigData& bigData);  
    BigData operator-(const 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:
    void INT64ToString();  
    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);  
    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 _value;
    std::string _strData;
};

Bignum.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "Bignum.h"

BigData::BigData(INT64 data)  
: _value(data)  
, _strData("")  
{
    INT64ToString();  
}
BigData::BigData(const char *_pdata)  
{  
    assert(_pdata);  
    char symbol = _pdata[0];  
    char* pdata = (char*)_pdata;  
    if (symbol == '+' || symbol == '-')  
    {  
        pdata++;  
    }  
    else if (*pdata >= '0'&& *pdata <= '9')  
    {  
        symbol = '+';  
    }  
    else  
    {  
        _value = 0;  
        _strData = '0';  
        return;  
    }  
    while (*pdata == '0')  
    {  
        pdata++;  
    }  
    _strData.resize(strlen(pdata) + 1);  
    _value = 0;  
    _strData[0] = symbol;  
    int count = 1;  
    while (pdata)  
    {  
        if (*pdata >= '0' && *pdata <= '9')  
        {  
            _value = _value * 10 + *pdata - '0';  
            _strData[count++] = *pdata++;  
        }  
        else  
        {  
            break;  
        }  
    }  

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

void BigData::INT64ToString()
{
    char symbol = '+';
    INT64 tmp = _value;
    if (tmp < 0)
    {
        symbol = '-';
        tmp = 0 - tmp;
    }
    _strData.append(1,symbol);
    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 tmp = *left;
        *left = *right;
        *right = tmp;
        *left++;
        *right--;
    }
}

bool BigData::IsINT64Overflow()const   
{  
    std::string tmp;  
    if ('+' == _strData[0])  
    {  
        tmp = "MAX_INT64";  
    }  
    else  
    {  
        tmp = "MIN_INT64";  
    }  
    if ((_strData.size() > tmp.size()) ||  
        ((_strData.size() == tmp.size())&&(_strData > tmp)))  
    {  
        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;  
} 
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 tmp;  
    tmp.resize(lsize + 1);  
    tmp[0] = ch;  
    char step = 0;  
    int n = 1;  
    while (n < lsize)  
    {  
        char ret = left[lsize - n] - '0' + step;  
        if (n < rsize)  
        {  
            ret += right[rsize - n] - '0';  
        }  
        tmp[lsize - n + 1] = (ret % 10 + '0');  
        step = ret / 10;  
        n++;  
    }  
    tmp[1] = step + '0';  

    return tmp;  
}
std::string BigData::Sub(std::string left, std::string right)  
{  
    int lsize = left.size();  
    int rsize = right.size();  
    char symbol = left[0];  
    if ((lsize < rsize) ||  
        (lsize == rsize && left < right))  
    {  
        std::swap(left, right);  
        std::swap(lsize, rsize);  
        if (symbol == '+')  
        {  
            symbol = '-';  
        }  
        else  
        {  
            symbol = '+';  
        }  
    }  
    std::string tmp;  
    tmp.resize(lsize);  
    tmp[0] = symbol;  
    int n = 1;  
    while (n < lsize)  
    {  
        char ret = left[lsize - n] - '0';  
        if (n < rsize)  
        {  
            ret -= right[rsize - n] - '0';  
        }  
        if (ret < 0)  
        {  
            left[lsize - n - 1] -= 1;  
            ret += 10;  
        }  
        tmp[lsize - n] = (ret + '0');  
        n++;  
    }  
    return tmp;  
}
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_INT64 + bigData._value >= _value)  
                || (_strData[0] == '-' && (MIN_INT64 + bigData._value) <= _value))  
            {  
                return BigData(_value - bigData._value);  
            }  
        }  
    }  
    std::string tmp;  
    if (_strData[0] != bigData._strData[0])  
    {  
        tmp = Add(_strData, bigData._strData);  
    }  
    else  
    {  
        tmp = Sub(_strData, bigData._strData);  
    }  
    return BigData(tmp.c_str());  
}  

BigData BigData::operator*(const BigData& bigData)  
{  
    if (_value == 0 || bigData._value == 0)  
    {  
        return BigData(INT64(0));  
    }  
    if (!IsINT64Overflow() && !bigData.IsINT64Overflow())  
    {  
        if (_strData[0] == bigData._strData[0])  
        {  
            if ((_strData[0] == '+' && MAX_INT64 / _value >= bigData._value)  
                || (_strData[0] == '-' && MAX_INT64 / _value <= bigData._value))  
            {  
                return BigData(_value * bigData._value);  
            }  
        }  
        else  
        {  
            if ((_strData[0] == '+' && MIN_INT64 / _value <= bigData._value)  
                || (_strData[0] == '-' && 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)  
{  
    int lsize = left.size();  
    int rsize = right.size();  
    if (lsize > rsize)  
    {  
        swap(left, right);  
        swap(lsize, rsize);  
    }  
    char symbol = '+';  
    if (left[0] != right[0])  
    {  
        symbol = '-';  
    }  
    string tmp;  
    tmp.assign(lsize + rsize - 1, '0');  
    tmp[0] = symbol;  
    int datalen = tmp.size();  
    int ioffset = 0;  
    for (int lidx = 1; lidx < lsize; lidx++)  
    {  
        char cleft = left[lsize - lidx] - '0';  
        char step = 0;  
        if (cleft == 0)  
        {  
            ioffset++;  
            continue;  
        }  
        for (int ridx = 1; ridx < rsize; ridx++)  
        {  
            char ret = cleft*(right[rsize - ridx]-'0');  
            ret += step;  
            ret += (tmp[datalen - ioffset - ridx] - '0');  
            tmp[datalen - ioffset - ridx] = (ret % 10 + '0');  
            step = ret / 10;  
        }   
        tmp[datalen - ioffset - rsize] += step;  
        ioffset++;  
    }  
    return tmp;  
}  
BigData BigData::operator/(const BigData& bigData)  
{  
    if (bigData._value == 0)  
    {  
        assert("除数不能为0");  
        return BigData(INT64(0));  
    }  
    if (!IsINT64Overflow() && bigData.IsINT64Overflow())  
    {  
        return BigData(_value / bigData._value);  
    }  
    return BigData(Div(_strData, bigData._strData).c_str());  
}  

int idx = 0;

std::string BigData::Div(std::string left, std::string right)  
{  
    char lsize = left.size();  
    char rsize = right.size();  
    char symbol = '+';  
    if (left[0] != right[0])  
    {  
        symbol = '-';  
    }  
    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] = symbol;  
            return left;  
        }  
    }  
    string tmp;  
    tmp.append(1, symbol);  
    char *pleft = (char*)(left.c_str() + 1);  
    char *pright = (char*)(right.c_str() + 1);  
    int datalen = 1;  
    lsize -= 1;  
    for (idx = 0; idx < lsize;)  
    {  
        if (*pleft == '0')  
        {  
            tmp.append(1, '0');  
            pleft++;  
            idx++;  
            continue;  
        }  
        if (!IsLeftStrBig(pleft, datalen, pright, rsize - 1))  
        {  
            tmp.append(1, '0');  
            datalen++;  
            if (idx + datalen > lsize)  
            {  
                break;  
            }  
            continue;  
        }    
        else  
        {  
            tmp.append(1,SubLoop(pleft, datalen, pright ,rsize - 1));  
            datalen++;  
        }  
    }  
    return tmp;  
}

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 ret = '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--;  
            idx++;  
        }  
        ret++;  
    }  
    return ret;  
} 

你可能感兴趣的:(c++项目)