大数运算

计算机中的各种类型的数据都是有其表示上限的当进行很大的数据运算时可能产生溢出,这时就要用的大数运算
大数运算是将数据保存在数组或者string,vector的容器中进行运算这样就可以进行几十位甚至上百位的运算

#pragma once

#include <string>
#include <iostream>
#include <unistd.h>
#include <stdlib.h>

enum FLAGS
{
    INT,
    DOUBLE
};


class BigNumber
{
public:
    BigNumber(const std::string& _num = "", FLAGS _flags = INT,bool _IsPositive = true);
    BigNumber(const BigNumber& big);

    ~BigNumber();

    BigNumber& operator=(const BigNumber& big);
    BigNumber operator+(BigNumber& big);
    BigNumber operator-(BigNumber& big);
    BigNumber operator*(BigNumber& big);
    BigNumber operator/(BigNumber& big);
    BigNumber operator%(BigNumber& big);
    BigNumber& operator+=(BigNumber& big);
    BigNumber& operator-=(BigNumber& big);
    BigNumber& operator*=(BigNumber& big);
    BigNumber& operator/=(BigNumber& big);
    BigNumber& operator%=(BigNumber& big);
    bool operator>(const BigNumber& big);
    bool operator<(const BigNumber& big);
    bool operator>=(const BigNumber& big);
    bool operator<=(const BigNumber& big);
    bool operator==(const BigNumber& big);
    bool operator!=(const BigNumber& big);
    BigNumber operator++(int);
    BigNumber& operator++();
    BigNumber operator--(int);
    BigNumber& operator--();
    void Print();

    friend std::ostream& operator<<(std::ostream& cout, const BigNumber& big);
private:
    BigNumber(const std::string _num, FLAGS _flags, int s, bool _IsPositive = true);
    int Addstr(size_t i, size_t j, std::string& str, std::string& str1, std::string& str2);
    void Substr(size_t i, size_t j, std::string& str, std::string str1, std::string str2,bool IsInt = true);
    void Mulstr(std::string& str, std::string& str1, std::string& str2);

public:
    bool IsPositive;
private:
    FLAGS flags;
    std::string num;
};
#include "bignumber.h"
#include <stdio.h>

BigNumber::BigNumber(const std::string& _num, FLAGS _flags, bool _IsPositive)
    : flags(_flags)
    , IsPositive(_IsPositive)
{
    int i = _num.length() - 1;
    for (i; i >= 0; i--)
    {
        num += _num[i];
    }
    int idx = num.find_first_of('.');
    if (idx > 0)
    {
        flags = DOUBLE;
    }
}
BigNumber::BigNumber(const std::string _num, FLAGS _flags, int s, bool _IsPositive)
    : flags(_flags)
    , num(_num)
    , IsPositive(_IsPositive)
{}

BigNumber::BigNumber(const BigNumber& big)
{
    flags = big.flags;
    num = big.num;
    IsPositive = big.IsPositive;
}

BigNumber::~BigNumber()
{}

BigNumber& BigNumber::operator=(const BigNumber& big)
{
    if (this == &big)
        return *this;

    flags = big.flags;
    num = big.num;
    IsPositive = big.IsPositive;
    return *this;
}

static bool CompareNum(const std::string& str1, const std::string& str2)
{
    std::string strint1;
    std::string strint2;
    std::string strfloat1;
    std::string strfloat2;
    int cutbit1 = str1.find_first_of('.');
    int cutbit2 = str2.find_first_of('.');
    if (cutbit1 > 0)
    {
        strint1 = str1.substr(cutbit1, str1.length() - 2);
        strfloat1 = str1.substr(cutbit1);
    }
    else
        strint1 = str1;
    if (cutbit2 > 0)
    {
        strint2 = str2.substr(cutbit2, str2.length() - 2);
        strfloat2 = str2.substr(cutbit2);
    }
    else
        strint2 = str2;
    int str1L = strint1.length() - 1;
    int str2L = strint2.length() - 1;
    while (str1L >= 0)                    //去除高位的0
    {
        if (strint1[str1L] == '0')
            str1L--;
        else
            break;

    }
    while (str2L >= 0)
    {
        if (strint2[str2L] == '0')
            str2L--;
        else
            break;
    }
    if (str1L > str2L)
    {
        return true;
    }
    else if (str1L < str2L)
    {
        return false;
    }

    if (strint1 == strint2)
    {
        if (strfloat2.empty() && !strfloat1.empty())
            return true;
        if (!strfloat2.empty() && strfloat1.empty())
            return false;
        int i = strfloat1.length() - 1;
        int j = strfloat2.length() - 1;
        while (i >= 0 && j >= 0)
        {
            if (strfloat1[i] != strfloat2[j])
            {
                if (strfloat1[i] > strfloat2[j])
                    return true;
                else
                    return false;
            }
            i--;
            j--;
        }
        if (i >= 0)
            return true;
        return false;
    }

    int i = strint1.length() - 1;
    while (i >= 0)
    {
        if (strint1[i] > strint2[i])
            return true;
        if (strint1[i]<strint2[i])
            return false;
        i--;
    }
}

bool BigNumber::operator>(const BigNumber& big)
{
    if (IsPositive && !big.IsPositive)
        return true;
    if (!IsPositive && big.IsPositive) 
        return false;
    if (num == big.num)
    {
        if (IsPositive == big.IsPositive)
            return true;
        if (IsPositive)
            return true;
        return false;
    }
    if (IsPositive)
    {
        return CompareNum(num, big.num);
    }
    return !CompareNum(num, big.num);
}

bool BigNumber::operator<(const BigNumber& big)
{
    return !(*this >= big);
}

bool BigNumber::operator==(const BigNumber& big)
{
    if (IsPositive == big.IsPositive && num == big.num)
        return true;
    return false;
}

bool BigNumber::operator!=(const BigNumber& big)
{
    return !(*this == big);
}

BigNumber BigNumber::operator++(int)
{
    BigNumber tmp(*this);
    BigNumber tmp1("1", INT, true);
    *this += tmp1;
    return tmp;
}

BigNumber& BigNumber::operator++()
{
    BigNumber tmp1("1", INT, true);
    *this += tmp1;
    return *this;
}

BigNumber BigNumber::operator--(int)
{
    BigNumber tmp(*this);
    BigNumber tmp1("1", INT, true);
    *this -= tmp1;
    return tmp;
}

BigNumber& BigNumber::operator--()
{
    BigNumber tmp1("1", INT, true);
    *this -= tmp1;
    return *this;
}

bool BigNumber::operator>=(const BigNumber& big)
{
    return (*this > big || *this == big);
}

bool BigNumber::operator<=(const BigNumber& big)
{
    return (*this < big || *this == big);
}

int BigNumber::Addstr(size_t i, size_t j, std::string& str,std::string& str1,std::string& str2)
{
    int cy = 0;
    for (i, j; i < str1.length() && j < str2.length(); i++, j++)
    {
        int num1 = str1[i] - '0';
        int num2 = str2[j] - '0';
        int num3 = num1 + num2 + cy;
        cy = num3 / 10;
        str += (num3 % 10 + '0');
    }
    if (i < str1.length())
    {
        for (; i < str1.length(); i++)
        {
            int num1 = str1[i] - '0';
            int num2 = num1 + cy;
            cy = num2 / 10;
            str += (num2 % 10 + '0');
        }
    }
    if (j < str2.length())
    {
        for (; j < str2.length(); j++)
        {
            int num1 = str2[j] - '0';
            int num2 = num1 + cy;
            cy = num2 / 10;
            str += (num2 % 10 + '0');
        }
    }
    return cy;
}

void BigNumber::Mulstr(std::string& str, std::string& str1, std::string& str2)
{
    int cy = 0;
    size_t count = 1;
    for (size_t i =0; i < str1.length(); i++)
    {
        if (str1[i] == '.')
            continue;
        int num1 = str1[i] - '0';
        cy = 0;
        std::string tmp1,tmp2;
        for (size_t j = 0; j < str2.length(); j++)
        {
            if (str2[j] == '.')
                continue;
            int num2 = str2[j] - '0';
            int num3 = num1*num2 + cy;
            cy = num3 / 10;
            tmp1 += (num3 % 10 + '0');
        }
        if (cy != 0)
            tmp1 += (cy + '0');
        if (str.length() == 0)
            str = tmp1;
        else
        {
            std::string tmp;
            for (size_t k = 0; k < count; k++)
                tmp += '0';
            count++;
            tmp += tmp1;
            cy = Addstr(0, 0, tmp2, str, tmp);
            if (cy != 0)
                tmp2 += (cy + '0');
            str = tmp2;
        }
    }
}

void BigNumber::Substr(size_t i, size_t j, std::string& str, std::string str1, std::string str2, bool IsInt)
{
    int cy = 0;
    if (!IsInt)
    {
        int str1L = str1.length();
        int str2L = str2.length();
        if (str1L < str2L)
        {
            std::string tmp;
            for (size_t k = 0; k < str2L - str1L; k++)
                tmp += '0';
            tmp += str1;
            str1 = tmp;
        }
        if (str1L > str2L)
        {
            std::string tmp; 
            for (size_t k = 0; k < str1L - str2L; k++)
                tmp += '0';
            tmp += str2;
            str2 = tmp;
        }
    }
    for (i, j; i < str1.length() && j < str2.length(); i++, j++)
    {
        int num1 = str1[i] - '0';
        int num2 = str2[j] - '0';
        if (cy && num1 > 0)
        {
            cy = 0;
            num1--;
        }
        if (cy && num1 == 0)
            num1 = 9;
        if (num1 < num2)
        {
            cy = 1;
            num1 += 10;
        }
        int num3 = num1 - num2;
        str += (num3 + '0');
    }

    for (i; i < str1.length(); i++)
    {
        int num1 = str1[i] - '0';
        if (cy && num1 > 0)
        {
            cy = 0;
            num1--;
        }
        if (cy && num1 == 0)
            num1 = 9;
        str += (num1 + '0');
    }
    for (j; j < str2.length(); j++)
    {
        int num1 = str2[j] - '0';
        if (cy && num1 > 0)
        {
            cy = 0;
            num1--;
        }
        if (cy && num1 == 0)
            num1 = 9;
        str += (num1 + '0');
    }
}

BigNumber& BigNumber::operator+=(BigNumber& big)
{
    *this = *this + big;
    return *this;
}

BigNumber& BigNumber::operator-=(BigNumber& big)
{
    *this = *this - big;
    return *this;
}

BigNumber& BigNumber::operator*=(BigNumber& big)
{
    *this = *this*big;
    return *this;
}

BigNumber& BigNumber::operator/=(BigNumber& big)
{
    *this = *this / big;
    return *this;
}

BigNumber& BigNumber::operator%=(BigNumber& big)
{
    *this = *this%big;
    return *this;
}

BigNumber BigNumber::operator+(BigNumber& big)
{
    int start1 = 0;
    int start2 = 0;

    if (!IsPositive && big.IsPositive)
    {
        BigNumber tmp(*this);
        tmp.IsPositive = true;
        return big - tmp;
    }

    if (IsPositive&&!big.IsPositive)
    {
        BigNumber tmp(big);
        tmp.IsPositive = true;
        return *this - tmp;
    }
    if (!IsPositive && !big.IsPositive)
    {
        BigNumber tmp1(*this);
        BigNumber tmp2(big);
        tmp1.IsPositive = true;
        tmp2.IsPositive = true;
        tmp1 = tmp1 + tmp2;
        tmp1.IsPositive = false;
        return tmp1;
    }
    if (INT == flags && INT ==big.flags)
    {
        std::string str;
        int cy = Addstr(start1, start2, str, num, big.num);
        if (cy != 0)
            str += (cy + '0');
        return BigNumber(str, INT, 0);
    }
    if ((INT == flags && DOUBLE == big.flags) || (DOUBLE == flags && INT == big.flags))
    {
        std::string str;
        std::string strint;
        std::string strfloat;
        start1 = num.find_first_of('.');
        if (start1 < 0)
            start1 = 0;
        else
            start1++;

        start2 = big.num.find_first_of('.');
        if (start2 < 0)
            start2 = 0;
        else
            start2++;

        int cy = Addstr(start1, start2, strint, num, big.num);
        if (cy != 0)
            strint += (cy + '0');
        if (DOUBLE == flags)
            strfloat = num.substr(0,num.find_first_of('.'));
        if (DOUBLE == big.flags)
            strfloat = big.num.substr(0, big.num.find_first_of('.'));

        strfloat += '.';
        str = strfloat + strint;
        return BigNumber(str, DOUBLE, 0);
    }
    if (DOUBLE == flags && DOUBLE == big.flags)
    {
        start1 = num.find_first_of('.');
        start2 = big.num.find_first_of('.');
        std::string str;
        int cy = Addstr(start1 + 1, start2 + 1, str, num, big.num);
        if (cy != 0)
            str += (cy + '0');
        cy = 0;
        std::string str1 = num.substr(0, start1);
        std::string str2 = big.num.substr(0, start2);
        std::string str3;
        int str1L = str1.length();
        int str2L = str2.length();
        if (str1L > str2L)
        {
            int i = 0;
            for (; i < str1L - str2L; i++)
                str3 += str1[i];
            cy = Addstr(i, 0, str3, str1, str2);
        }
        else if (str2L == str1L)
        {
            cy = Addstr(0, 0, str3, str1, str2);
        }
        else
        {
            int i = 0;
            for (; i < str2L - str1L; i++)
                str3 += str2[i];
            cy = Addstr(0, i, str3, str1, str2);
        }
        if (cy != 0)
        {
            std::string str4;
            str4 += (cy + '0');
            std::string tmp;
            cy = Addstr(0, 0, tmp, str, str4);
            if (cy != 0)
                tmp += (cy + '0');
            str = tmp;
        }
        str3 += '.';
        str3 += str;
        return BigNumber(str3, DOUBLE, 0);
    }

    return BigNumber();
}

BigNumber BigNumber::operator-(BigNumber& big)
{
    if (*this == big)
    {
        std::string str;
        return BigNumber(str,INT,0,true);
    }
    if (!big.IsPositive)
    {
        BigNumber tmp(big);
        tmp.IsPositive = true;
        return *this + tmp;
    }
    std::string str;
    if (INT == flags && INT == big.flags)
    {
        if (*this > big)
        {
            Substr(0, 0, str, num, big.num);
            return BigNumber(str, INT, 0, true);
        }
        else
        {
            Substr(0, 0, str, big.num, num);
            return BigNumber(str, INT, 0, false);
        }
    } 

    if (INT == flags && DOUBLE == big.flags)
    {
        std::string strint = big.num.substr(big.num.find_first_of('.')+1, big.num.length());
        std::string strfloat = big.num.substr(0,big.num.find_first_of('.'));
        if (strint == num)
        {
            strfloat += ".0";
            return BigNumber(strfloat, DOUBLE, 0, false);
        }
        if (CompareNum(num, strint))
        {
            Substr(0, 0, str, num, strint);
            strfloat += '.';
            strfloat += str;
            return BigNumber(strfloat, DOUBLE, 0, true);
        }
        else
        {
            Substr(0, 0, str, strint, num);
            strfloat += ".";
            strfloat += str;
            return BigNumber(strfloat, DOUBLE, 0, false);
        }
    }
    if (DOUBLE == flags && INT == big.flags)
    {
        std::string strint = num.substr(num.find_first_of('.')+1, num.length());
        std::string strfloat = num.substr(0,num.find_first_of('.'));
        if (strint == big.num)
        {
            strfloat += ".0";
            return BigNumber(strfloat, DOUBLE, 0, true);
        }
        if (CompareNum(strint, big.num))
        {
            Substr(0, 0, str, strint, big.num);
            strfloat += '.';
            strfloat += str;
            return BigNumber(strfloat, DOUBLE, 0, true);
        }
        else
        {
            Substr(0, 0, str, big.num, strint);
            strfloat += '.';
            strfloat += str;
            return BigNumber(strfloat, DOUBLE, 0, false);
        }
    }
    int cutbit1 = num.find_first_of('.');
    int cutbit2 = big.num.find_first_of('.');
    std::string strint1 = num.substr(cutbit1 + 1, num.length());
    std::string strint2 = big.num.substr(cutbit2 + 1, big.num.length());
    std::string strfloat1 = num.substr(0, cutbit1);
    std::string strfloat2 = big.num.substr(0, cutbit2);
    if (*this < big)
    {
        BigNumber tmp = big - *this;
        tmp.IsPositive = false;
        return tmp;
    }
    if (strint1 == strint2)
    {
        Substr(0, 0, str, strfloat1, strfloat2);
        str += ".0";
        return BigNumber(str, DOUBLE, 0, true);
    }

    int i = strfloat1.length() - 1;
    int j = strfloat2.length() - 1;
    while (i >= 0 && j >= 0)
    {
        if (strfloat1[i] != strfloat2[j])
            break;
    }
    if (strfloat1[i] > strfloat2[j])
    {
        Substr(0, 0, str, strfloat1, strfloat2, false);
        str += '.';
    }
    else
    {
        std::string tmp;
        Substr(0, 0, tmp, str, "1");
        str = tmp;
        strfloat1 += '1';
        Substr(0, 0, str, strfloat1, strfloat2, false);
        str += '.';
    }

    Substr(0, 0, str, strint1, strint2);
    return BigNumber(str, DOUBLE, 0, true);
}

BigNumber BigNumber::operator*(BigNumber& big)
{
    int start1 = 0;
    int start2 = 0;
    std::string str;
    Mulstr(str, num, big.num);
    if (INT == flags && INT == big.flags)
    {
        if(IsPositive==big.IsPositive)
            return BigNumber(str, INT, 0);
        else
            return BigNumber(str, INT, 0,false);
    }
    if (DOUBLE == flags)
        start1 = num.find_first_of('.');
    if (DOUBLE == big.flags)
        start2 = big.num.find_first_of('.');
    std::string strfloat = str.substr(0, start1 + start2);
    std::string strint = str.substr(start2 + start1);
    strfloat += '.';
    str = strfloat + strint;
    if (IsPositive == big.IsPositive)
        return BigNumber(str, DOUBLE, 0);
    else
        return BigNumber(str,DOUBLE,0,false);
}

BigNumber BigNumber::operator/(BigNumber& big)
{
    if (big.num.empty())
    {
        std::cout << "被除数为0错误" << std::endl;
        //exit(1);
    }
    if (num.empty() || *this < big)
    {
        return BigNumber();
    }
    if (big.num.length() == 1 && big.num[0] == '1')
    {
        return *this;
    }
    if (*this == big)
    {
        return BigNumber("1", flags, 0, true);
    }
    BigNumber number1;
    BigNumber number2(*this);
    do 
    {
        ++number1;
        number2 = number2 - big;
    } while (number2 > big);
    return number1;
}

BigNumber BigNumber::operator%(BigNumber& big)
{
    if (DOUBLE == big.flags)
    {
        std::cout << "不能模小数" << std::endl;
        //exit(1);
    }
    if (big.num.empty())
    {
        std::cout << "不能模0" <<std::endl;
        //exit(1);
    }
    if (num.empty() || *this == big)
    {
        return BigNumber();
    }
    if (*this < big)
    {
        return *this;
    }
    BigNumber number1;
    BigNumber number2(*this);
    do
    {
        ++number1;
        number2 = number2 - big;
    } while (number2 > big);
    return number2;
}


std::ostream& operator<<(std::ostream& cout, const BigNumber& big)
{
    if (big.num.empty())
    {
        cout << 0;
        return cout;
    }

    int i = big.num.length() - 1;
    while (big.num[i] == '0')
        i--;
    if (!big.IsPositive)
        cout << '-';
    for (; i >= 0; --i)
    {
        cout << big.num[i];
    }
    return cout;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值