c++高精度类

头文件 - intx.h

//intx.h
#ifndef INTX_H_
#define INTX_H_
#include <iostream>
#include <cstring>
#include <string>
class intx
{
private:
    bool sign;
    int *num;
    int len;
    static int process_char(const char *s,bool &sign,int *&num);
    static bool unsign_gt(const int *a,const int lena,const int *b,const int lenb);
    static bool unsign_gte(const int *a,const int lena,const int *b,const int lenb);
    static int unsign_plus(const int *a,int lena,const int *b,int lenb,int *&result);
    static int unsign_minus(const int *a,int lena,const int *b,int lenb,int *&result);
    static int multiply_base(const int *a,const int lena,int n,int *&result);
    static int unsgin_multiply(const int *a,const int lena,const int *b,const int lenb,int *&result);
    static bool divide_gte(const int *a,int end,const int *b,int lenb);
    static int unsign_divide(const int *a,const int lena,const int *b,const int lenb,int *&result);
    static int unsign_mod(const int *a,const int lena,const int*b,const int lenb,int *&result);
public:
//constructor
    intx();
    intx(const char * s);
    intx(const std::string & str);
    intx(int n);
    intx(const intx &b);
//destructor
    ~intx();
//calc
    bool operator==(const intx &b) const;
    bool operator>(const intx &b) const;
    bool operator>=(const intx &b) const;
    bool operator<(const intx &b) const;
    bool operator<=(const intx &b) const;
    intx operator-()const;
    intx operator+(const intx &b) const;
    intx operator-(const intx &b) const;
    intx operator*(const intx &b) const;
    intx operator/(const intx &b) const;
    intx operator%(const intx &b) const;
//others
    friend std::ostream& operator<<(std::ostream &os,const intx &a);
    friend std::istream& operator>>(std::istream &is,intx &a);
    int& operator[](const int sub) const;
    intx& operator=(const intx &b);
    intx& operator=(const char *s);
    intx& operator=(const std::string &str);
    int size(){return len;}
    bool IsNatural()const{return sign;}
};
#endif

实现文件 - intx.cpp

//intx.cpp
#include "intx.h"

//private
int intx::process_char(const char *s,bool &sign,int *&num)
{
    int len = strlen(s);
    if(!len)//len == 0
    {
        sign = true;
        num = new int[1];
        num[0] = 0;
        len = 1;
    }
    else
        switch(s[0])
        {
        case '+':
            sign = true;
            --len;
            num = new int[len];
            for(int i = 0;i < len;++i)
                num[i] = s[i + 1] - '0';
            break;
        case '-':
            sign = false;
            --len;
            num = new int[len];
            for(int i = 0;i < len;++i)
                num[i] = s[i + 1] - '0';
            break;
        default:
            sign = true;
            num = new int[len];
            for(int i = 0;i < len;++i)
                num[i] = s[i] - '0';
            break;
        }
    return len;
}
bool intx::unsign_gt(const int *a,const int lena,const int *b,const int lenb)
{
    if(lena < lenb)
        return false;
    else if(lena > lenb)
        return true;
    else
    {
        for(int i = 0;i < lena;++i)
            if(a[i] < b[i])
                return false;
            else if(a[i] > b[i])
                return true;
        return false;
    }
}
bool intx::unsign_gte(const int *a,const int lena,const int *b,const int lenb)
{
    if(lena < lenb)
        return false;
    else if(lena > lenb)
        return true;
    else
    {
        for(int i = 0;i < lena;++i)
            if(a[i] < b[i])
                return false;
            else if(a[i] > b[i])
                return true;
        return true;
    }
} 
int intx::unsign_plus(const int *a,int lena,const int *b,int lenb,int *&result)
{
    int rem;
    if(lenb > lena)
    {
        const int *temp = a;
        a = b;
        b = temp;
        rem = lena;
        lena = lenb;
        lenb = rem;
    }
    int len = lena + 1;
    result = new int[len];
    int sub = lena;
    rem = 0;
    --lena;
    --lenb;
    while(lenb >= 0)
    {
        rem += a[lena--] + b[lenb--];
        result[sub--] = rem % 10;
        rem /= 10;
    }
    while(lena >= 0)
    {
        rem += a[lena--];
        result[sub--] = rem %10;
        rem /= 10;
    }
    if(rem > 0)
    {
        result[sub] = rem;
    }
    else
    {
        --len;
        int *p = new int[len];
        memcpy(p,result + 1,sizeof(int)*len);
        delete[] result;
        result = p;
    }
    return len;
}
int intx::unsign_minus(const int *a,int lena,const int *b,int lenb,int *&result)//a must > b
{
    int len = lena;
    result = new int[len];
    memcpy(result,a,sizeof(int)*len);//const int *a can't modify
    --lenb;
    --lena;
    while(lenb >= 0)
    {
        if(a[lena] >= b[lenb])
            result[lena] -= b[lenb];
        else
        {
            result[lena] += 10 - b[lenb];
            --result[lena -1];
        }
        --lena;
        --lenb;
    }
    while(lena>=0)
    {
        if(result[lena] < 0)
        {
            result[lena] += 10;
            --result[lena - 1];
            --lena;
        }
        else
            break;
    }
    int zero = 0;
    while(zero < len)
        if(result[zero] == 0)
            ++zero;
        else
            break;
    if(zero == len)
    {
        delete[] result;
        result = new int[1]{0};
        len = 1;
    }
    else if(zero != 0)
    {
        len -= zero;
        int *p = new int[len];
        memcpy(p,result + zero,sizeof(int)*len);
        delete[] result;
        result = p;
    }
    return len;
}
bool intx::divide_gte(const int *a,const int end,const int *b,const int lenb)
{
    int begin = 0;
    while(a[begin] == 0)
    {
        ++begin;
    }
    if(end - begin  + 1 < lenb)
        return false;
    else if(end - begin + 1 > lenb)
        return true;
    else
    {
        for(int i = 0;i < lenb;++begin,++i)
            if(a[begin] > b[i])
                return true;
            else if(a[begin] < b[i])
                return false;
        return true;
    }
}
int intx::multiply_base(const int *a,int lena,const int n,int * &result)//the first may be 0
{
    int len = lena + 1;
    result = new int[len];
    int rem = 0;
    int sub = lena;
    --lena;
    while(lena >= 0)
    {
        rem += n * a[lena];
        result[sub] = rem % 10;
        rem /= 10;
        --lena;
        --sub;
    }
    if(rem > 0)
        result[sub] = rem;
    else
        result[sub] = 0;
    return len;
}
int intx::unsgin_multiply(const int *a,const int lena,const int *b,const int lenb,int *&result)//a on the top
{
    int len = lena + lenb;
    result = new int[len]{0};
    int *MultiplyTemp;
    int MultiplyBit = lenb - 1;//the subscript of number in the b to be multiplied
    while(MultiplyBit >= 0)
    {
        int MultiplyTempSub = multiply_base(a,lena,b[MultiplyBit],MultiplyTemp);
        //plus
        int rem = 0;
        int sub = len - (lenb - MultiplyBit);//the bit when result begin plus
        --MultiplyTempSub;
        while(MultiplyTempSub >= 0)
        {
            rem += result[sub] + MultiplyTemp[MultiplyTempSub];
            result[sub] = rem % 10;
            rem /= 10;
            --sub;
            --MultiplyTempSub;
        }
        if(rem > 0)
            result[sub] += rem;
        --MultiplyBit;
        delete[] MultiplyTemp;
    }
    int zero = 0;
    while(zero < len)
        if(result[zero] == 0)
            ++zero;
        else
            break;
    if(zero == len)
    {
        delete[] result;
        result = new int[1]{0};
        return 1;
    }
    else if(zero != 0)
    {
        len -= zero;
        int *p = new int[len];
        memcpy(p,result + zero,sizeof(int)*len);
        delete[] result;
        result = p;
    }   
    return len;
}
int intx::unsign_divide(const int *a,const int lena,const int *b,const int lenb,int *&result)
{
    if(lena < lenb)
    {
        result = new int[1]{0};
        return 1;
    }
    //Judge the first bit
    int CurrentBit = lenb - 1;//the current number on the consult
    int len;
    if(!divide_gte(a,CurrentBit,b,lenb))
        if(CurrentBit + 1== lena)//lena == lenb && a < b
        {
            result = new int[1]{0};
            return 1;
        }
        else
        {
            ++CurrentBit;
            len = lena - lenb;
            result = new int[len];
        }
    else
    {
        len = lena - lenb + 1;
        result = new int[len];
    }
    //copy
    int *A = new int[lena];
    memcpy(A,a,sizeof(int)*lena);
    int sub = 0;//sub = CurrentBit - (lena - lenb),too much calc
    while(CurrentBit < lena)
    {
        result[sub] = 0;
        do
        {
            //minus
            int Asub = CurrentBit;
            for(int i = lenb - 1;i >= 0;--Asub,--i)
                if(A[Asub] >= b[i])
                    A[Asub] -= b[i];
                else
                {
                    A[Asub] += 10 - b[i];
                    --A[Asub - 1];
                }
            while(Asub >= 0)
                if(A[Asub] < 0)
                {
                    A[sub] += 10;
                    --A[Asub - 1];
                    --Asub;
                }
                else
                    break;
            ++result[sub];
        }while(divide_gte(A,CurrentBit,b,lenb));
        if(++sub,++CurrentBit == lena)
            break;
        while(!divide_gte(A,CurrentBit,b,lenb))
        {
            result[sub] = 0;
            if(++sub,++CurrentBit == lena)
                break;
        }
    }
    delete[]A;
    return len;
}
int intx::unsign_mod(const int *a,const int lena,const int *b,const int lenb,int *&result)
{
    int len = lena;
    result = new int[len];
    memcpy(result,a,sizeof(int)*len);
    if(lena < lenb)
        return len;
    //Judge the first bit
    int CurrentBit = lenb - 1;//the current number on the consult
    if(!divide_gte(result,CurrentBit,b,lenb))
    {
        if(CurrentBit + 1== len)//lena == lenb && a < b
            return len;
        else
            ++CurrentBit;
    }
    while(CurrentBit < len)
    {
        do
        {
            //minus
            int sub = CurrentBit;
            for(int i = lenb - 1;i >= 0;--sub,--i)
                if(result[sub] >= b[i])
                    result[sub] -= b[i];
                else
                {
                    result[sub] += 10 - b[i];
                    --result[sub - 1];
                }
            while(sub >= 0)
                if(result[sub] < 0)
                {
                    result[sub] += 10;
                    --result[sub - 1];
                    --sub;
                }
                else
                    break;
        }while(divide_gte(result,CurrentBit,b,lenb));
        while(++CurrentBit != len)
            if(divide_gte(result,CurrentBit,b,lenb))
                break;
    }
    int zero = 0;
    while(zero < len)
        if(result[zero] == 0)
            ++zero;
        else
            break;
    if(zero == len)
    {
        delete[] result;
        result = new int[1]{0};
        len = 1;
    }
    else if(zero != 0)
    {
        len -= zero;
        int *p = new int[len];
        memcpy(p,result + zero,sizeof(int)*len);
        delete[] result;
        result = p;
    }
    return len;
}
//constructor
intx::intx()
{
    sign = true;
    num = new int[1];
    num[0] = 0;
    len = 1;
}
intx::intx(const char *s)
{
    len = process_char(s,sign,num);
}
intx::intx(const std::string &str)
{
    const char *s = str.data();
    new (this)intx(s); 
}
intx::intx(int n)
{
    if(n < 0)
        sign = false;
    else
        sign = true;
    if(n == 0)
    {
        len = 1;
        num = new int[1]{0};
        return;
    }
    len = 0;
    int N = n;
    while(n > 0)
    {
        n /= 10;
        ++len;
    }
    num = new int[len];
    for(int i = len;i > 0;--i)
    {
        num[i - 1] = N % 10;
        N /= 10;
    }
}
intx::intx(const intx &b)
{
    sign = b.sign;
    len =  b.len;
    num = new int[len];
    memcpy(num,b.num,sizeof(int) * len);
}
//destructor
intx::~intx()
{
    delete[] num;
}

//calc
bool intx::operator==(const intx &b) const
{
    if(len != b.len)
        return false;
    else if(sign != b.sign)
        return false;
    else
    {
        for(int i = 0;i < len;++i)
            if(num[i] != b.num[i])
                return false;
        return true;
    }
}
bool intx::operator>(const intx &b) const
{
    if(sign)
        if(b.sign)
            return unsign_gt(num,len,b.num,b.len);
        else
            return true;
    else
        if(b.sign)
            return false;
        else
            return !unsign_gt(num,len,b.num,b.len);
}
bool intx::operator>=(const intx &b)const
{
    if(sign)
        if(b.sign)
            return unsign_gte(num,len,b.num,b.len);
        else
            return true;
    else
        if(b.sign)
            return false;
        else
            return !unsign_gte(num,len,b.num,b.len);
}
bool intx::operator<(const intx &b) const
{
    return !(*this >= b);
}
bool intx::operator<=(const intx &b) const
{
    return !(*this > b);
}
intx intx::operator-()const
{
    intx b = *this;
    b.sign = !b.sign;
    return b;
}
intx intx::operator+(const intx &b) const
{
    intx sum;
    delete[] sum.num;
    if(sign)//a >= 0
        if(b.sign)//a > 0 && b > 0
        {
            sum.sign = true;
            sum.len = unsign_plus(num,len,b.num,b.len,sum.num);
        }
        else if(unsign_gte(num,len,b.num,b.len))// a > 0,b < 0,|a| >= |b|
        {
            sum.sign = true;
            sum.len = unsign_minus(num,len,b.num,b.len,sum.num);
        }
        else// a > 0,b < 0,|a| < |b|
        {
            sum.sign = false;
            sum.len = unsign_minus(b.num,b.len,num,len,sum.num);
        }
    else//a < 0
    {
        if(!b.sign)// a < 0, b < 0
        {
            sum.sign = false;
            sum.len = unsign_plus(num,len,b.num,b.len,sum.num);
        }
        else if(unsign_gte(b.num,b.len,num,len))// a < 0,b > 0,|a| <= |b|
        {
            sum.sign = true;
            sum.len = unsign_minus(b.num,b.len,num,len,sum.num);
        }
        else//a < 0 b > 0 , |a| > |b|
        {
            sum.sign = false;
            sum.len = unsign_minus(num,len,b.num,b.len,sum.num);
        }
    }
    return sum;
}
intx intx::operator-(const intx &b)const
{
    return *this + (-b);
}
intx intx::operator*(const intx &b)const
{
    intx product;
    if(sign == b.sign)
        product.sign = true;
    else
        product.sign = false;
    delete[] product.num;
    product.len = unsgin_multiply(num,len,b.num,b.len,product.num);
    return product;
}
intx intx::operator/(const intx &b) const
{
    intx consult;
    if(sign == b.sign)
        consult.sign = true;
    else
        consult.sign = false;
    delete[] consult.num;
    consult.len = unsign_divide(num,len,b.num,b.len,consult.num);
    if(consult[0] == 0)//avoid "-0"
        consult.sign = true;
    return consult;
}
intx intx::operator%(const intx &b)const
{
    intx modulo;
    delete[] modulo.num;
    modulo.sign = sign;
    modulo.len = unsign_mod(num,len,b.num,b.len,modulo.num);
    return modulo;
}
//others
std::ostream& operator<<(std::ostream &os,const intx &a)
{
    if(!a.sign)
        os << '-';
    for(int i = 0;i < a.len;++i)
        os << a.num[i];
    return os;
}
std::istream& operator>>(std::istream &is,intx &a)
{
    delete[] a.num;
    int max = 16;
    a.num = new int[max];
    //Judge sign
    char c;
    a.len = 0;
    c = getchar();
    if(c == '-')
        a.sign = false;
    else if(c == '+')
        a.sign = true;
    else if(c <= '9' && c >= '1')//the first num
    {
        a.num[a.len] = c - '0';
        ++a.len;
    }
    else
    {
        a.sign = true;
        a.num[a.len] = 0;
        ++a.len;
        return is;
    }
    //makesure the first bit is inputed
    if(a.len == 0)
    {
        c = getchar();
        if(c >= '1' && c <= '9')
        {
            a.num[a.len] = c - '0';
            ++a.len;
        }
        else
        {
            a.sign = true;
            a.num[a.len] = 0;
            ++a.len;
            return is;
        }
    }
    while(c = is.peek(),c >= '0' && c <= '9')
    {
        is >> c;
        a.num[a.len] = c - '0';
        if(++a.len == max)
        {
            max *= 2;
            int *temp = new int[max];
            memcpy(temp,a.num,sizeof(int)*a.len);
            delete[] a.num;
            a.num = temp;
        }
    }
    return is;
}
int & intx::operator[](const int sub) const
{
    return num[len - 1 - sub];
}
intx& intx::operator=(const intx &b)
{
    if(this == &b)
        return *this;
    else
    {
        len = b.len;
        sign = b.sign;
        delete[] num;
        num = new int[len];
        memcpy(num,b.num,sizeof(int) * len);
        return *this;
    }
}
intx& intx::operator=(const char *s)
{
    delete[] num;
    len = process_char(s,sign,num);
    return *this;
}
intx& intx::operator=(const std::string &str)
{
    delete[] num;
    len = process_char(str.data(),sign,num);
    return *this;
}

转载于:https://www.cnblogs.com/h-hg/p/8366142.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值