大整数类C++实现——关键代码

    相信很多编程新手都上google,baidu搜过这类东西。 我也是因为这样才终于下决心自己动手完善一个大整数类,虽然C++效率不如C,不过只是关键算法明白就好,写成类只是心理痛快点。

    先看头文件代码:

基本的C++类什么的就不详细讲了,主要说一下设计思路。

#define MAXLEN 1000
#define POSITIVE 1
#define NEGATIVE -1
#define ZERO 0

class HugeInt
{
    friend ostream& operator<<(ostream& output,const HugeInt& n);
    public:

    /*  构造函数    */
        HugeInt(int=0);
        HugeInt(char *str);
        HugeInt(const HugeInt& other);
        HugeInt& operator=(const HugeInt& other);

    /*  关系运算符   */
        bool operator==(const HugeInt &other)const;
        bool operator==(const int &x)const;
        bool operator!=(const HugeInt &other)const;
        bool operator!=(const int &x)const;

        bool operator>(const HugeInt &other)const;
        bool operator>(const int &x)const;
        bool operator>=(const HugeInt &other)const;
        bool operator>=(const int &x)const;

        bool operator<(const HugeInt &other)const;
        bool operator<(const int &x)const;
        bool operator<=(const HugeInt &other)const;
        bool operator<=(const int &x)const;

    /*  加法运算    */
        HugeInt operator+(const HugeInt &other)const;
        HugeInt operator+(const int &x)const;
        HugeInt operator+=(const HugeInt &other);
        HugeInt operator+=(const int &x);
        HugeInt& operator++();//前置
        HugeInt operator++(int);//后置

    /*  减法运算    */
        HugeInt operator-();//负号
        HugeInt operator-(const HugeInt &other)const;
        HugeInt operator-(const int &x)const;
        HugeInt operator-=(const HugeInt &other);
        HugeInt operator-=(const int &x);
        HugeInt& operator--();//前置
        HugeInt operator--(int);//后置

    /*  乘法运算    */
        HugeInt operator*(const HugeInt &other)const;
        HugeInt operator*(const int &x)const;
        HugeInt operator*=(const HugeInt &other);
        HugeInt operator*=(const int &x);

    /*  除法运算    */
        HugeInt operator/(const HugeInt &other)const;
        HugeInt operator/(const int &x)const;
        HugeInt operator/=(const HugeInt &other);
        HugeInt operator/=(const int &x);

    /*  求模运算    */
        HugeInt operator%(const HugeInt &other)const;//to do:debug
        int operator%(const int &x)const;
        HugeInt operator%=(const HugeInt &other);
        int operator%=(const int &x);

    private:
        char num[MAXLEN];
        int length;
        int sign;
        bool isZero()const;
};
用C++主要是因为运算符重载比较爽。

成员里用一个char类型数组存数,length表示长度,int类型的sign表示负号,定义了仨宏,看着方便点,用int类型也是因为比较大小的时候很方便,单独存符号比掺合到数组里方便不少!

全部的头文件代码都在这了,cpp里的不会贴这么多,像+=这样的符号都是直接引用+号的。

下面是cpp:

HugeInt::HugeInt(int x) //构造函数
{
    memset(num,0,sizeof(num));
    if(x == 0)
    {
        sign=ZERO;
        length=1;
    }
    else
    {
        if(x > 0)
            sign=POSITIVE;
        else
        {
            sign=NEGATIVE;
            x = -x;
        }
        int i=0;
        while(x != 0)
        {
            num[i++] = x%10;
            x /= 10;
        }
        length = i;
    }
}
HugeInt::HugeInt(char *str)//构造函数
{
    memset(num,0,sizeof(num));
    if(str[0]=='-')
        sign=NEGATIVE;
    else
        sign=POSITIVE;


    int i,j,k,n=strlen(str);
    for(i=0;i<n;i++)
        if(str[i]>'0' && str[i]<='9')break;


    if(i==n)
    {
        sign=ZERO;
        length=1;
        num[0]=0;
    }
    else
    {
        for(k=n-1,j=0;k>=i;--k,++j)
            num[j]=str[k]-'0';
        length=j;
    }
}
bool HugeInt::operator>(const HugeInt &other)const//大于号
{
    if(this->sign == other.sign)
    {
        bool flag=(sign == POSITIVE);
        if(this->length != other.length)
            return flag&(this->length > other.length);
        else
        {
            int i;
            for(i=length-1;i>=0;--i)
                if(this->num[i] > other.num[i])
                    return (flag?true:false);
                else if(this->num[i] < other.num[i])
                    return (flag?false:true);
            return false;
        }
    }
    else
        return (this->sign > other.sign);//int 类型的sign方便就方便在这了
}
HugeInt HugeInt::operator+(const HugeInt &other)const//加法
{
    if(this->isZero())
        return other;
    if(other.isZero())
        return *this;


    HugeInt temp(0);
    if(this->sign == other.sign)
    {
        int maxlength=max(length,other.length);
        int i;
        for(i=0;i<maxlength;++i)
        {
            temp.num[i] += (num[i]+other.num[i]);
            temp.num[i+1] += temp.num[i]/10;
            temp.num[i] = temp.num[i]%10;
        }
        temp.sign=sign;
        temp.length=maxlength;
        if(temp.num[temp.length])
            temp.length++;
        return temp;
    }
    else if(this->sign == NEGATIVE)
    {
        temp=(*this);
        temp.sign=POSITIVE;
        return (other-temp);
    }
    else
    {
        temp=other;
        temp.sign=POSITIVE;
        return ((*this)-temp);
    }
}
HugeInt HugeInt::operator-(const HugeInt &other)const//减法
{
    if((*this) < other)
        return -(other - (*this));
    else if((*this) == other)
        return HugeInt(0);
    else
    {
        HugeInt temp(*this);
        int i;
        for(i=0;i<temp.length;++i)
            if(temp.num[i] < other.num[i])
            {
                --temp.num[i+1];
                temp.num[i] = temp.num[i]+10-other.num[i];
            }
            else
                temp.num[i] -= other.num[i];
        for(i=temp.length;i>=0;--i)
            if(temp.num[i])
            {
                temp.length = i+1;
                break;
            }
        return temp;
    }
}
HugeInt HugeInt::operator*(const HugeInt &other)const//乘法
{
    if(this->isZero() || other.isZero())
        return HugeInt(0);
    else
    {
        int i,j;
        HugeInt temp(0);
        for(i=0;i < this->length;++i)
            for(j=0;j < other.length;++j)
            {
                temp.num[i+j] += (num[i]*other.num[j]);
                temp.num[i+j+1] += temp.num[i+j]/10;
                temp.num[i+j] %= 10;
            }
        temp.length=(i-1)+(j-1)+1;
        if(temp.num[temp.length])
            ++temp.length;
        temp.sign = this->sign * other.sign;
        return temp;
    }
}
HugeInt HugeInt::operator/(const HugeInt &other)const//除法,另需一个函数,在下面
{
    if(this->length < other.length)return HugeInt(0);


    int i,t,z;
    HugeInt result(0),n1(*this),n2(other);


    result.sign = n1.sign * n2.sign;
    t=n1.length - n2.length;
    if(t > 0)
        for(i=length;i>=0;--i)
            if(i-t >= 0)n2.num[i] = n2.num[i-t];
            else        n2.num[i] = 0;
    n2.length = n1.length;
    for(i=0;i<=t;++i)
        while((z=subtract(n1.num,(n2.num)+i,n1.length,n2.length-i))>=0)
        {
            n1.length = z;
            result.num[t-i]++;
        }
    for(i=MAXLEN-1;i>=0;--i)
        if(result.num[i])break;
    if(i>=0)result.length = i+1;
    else    return HugeInt(0);
    return result;
}
int subtract(char *p1,char *p2,int len1,int len2)
{
    int i;
    if(len1 < len2)return -1;
    else if(len1 == len2)
    {
        for(i=len1-1;i>=0;--i)
            if(p1[i] < p2[i])       return -1;
            else if(p1[i] > p2[i])  break;
        if(i < 0)return 0;
    }
    for(i=0;i<len1;++i)
        if(p1[i] < p2[i])
        {
            p1[i+1]--;
            p1[i] = p1[i]+10-p2[i];
        }
        else
            p1[i] -= p2[i];
    for(i=len1-1;i>=0;--i)
        if(p1[i])   return i+1;
    return 0;
}
HugeInt HugeInt::operator%(const HugeInt &other)const//模运算,跟除法一样,就是返回的不同
{
    if(this->length < other.length)return *this;


    int i,t,z;
    HugeInt n1(*this),n2(other);


    t=n1.length - n2.length;
    if(t > 0)
        for(i=length;i>=0;--i)
            if(i-t >= 0)n2.num[i] = n2.num[i-t];
            else        n2.num[i] = 0;
    n2.length = n1.length;
    for(i=0;i<=t;++i)
        while((z=subtract(n1.num,(n2.num)+i,n1.length,n2.length-i))>=0)
        {
            if(z == 0)return HugeInt(0);
            n1.length = z;
        }
    return n1;
}
int HugeInt::operator%(const int &x)const//大数模小数,不需要大整数除法
{
    int i,exp10[this->length+1],k=0;
    exp10[0]=1%x;
    exp10[1]=10%x;
    for(i=2;i<=this->length;++i)
        exp10[i] = exp10[i-1]*exp10[1]%x;
    for(i=0;i<this->length;++i)
        k = (k+(this->num[i])%x*exp10[i])%x;
    return k;
}
上面是几种运算的核心代码,加减法主要是分类讨论,互相“推卸责任”,加法不同号推给减法等等。。

乘法就是模拟手算,第i位乘以另一个数的第j位结果加到第i+j位就好,原理跟手算一样,拿笔画画就明白了,符号非常好处理。

除法也基本上是模拟手算,只不过试商的过程改成了减法,比如100除以3,商33,就需要算3次100减30和3次10减3,时间复杂度我也琢磨不清楚。大数模大数的运算和除法一样,返回余数。大数模小数的运算有一个公式推出来的,不太容易讲,是在百度知道上搜到的。

上面这些算法都是最思路上最简单的,没有任何优化,是因为我能力还很有限啊~说起来我只不过干了个体力活而已。原理我也没有详细说,网上都搜的到。

完整的代码我另写一篇日志贴上去把,头一次用 csdn博客,请多指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值