大整数类的实现(1)(原创)

       每次上论坛都能找到类似求100!的问题,其实这些题目归根究底就是一个大整数类的实现。

一般大家提到的方法是用数组,每个数字要么表示一个10进制位,要么表示几个10进制位。我觉得这样虽然在对“人”是直观了,但是对“电脑”却非常不直观,所以我觉得应该按照计算机的2进制表示方式来实现。

       按照自己的想法,我写了这样一个大整数类,内部用long的数组来表示,是在2进制层面,即2个long表示了2^64 bits以内的数值,4个long表示了2^128 bits以内的数值。

为了与原始整数类型一致(我在设计时考虑的最多的就是这个因素了),我分了signed和unsigned,在运算符重载,类型转化,使用方式等方面尽量接近原始的long和unsigned long类型。但是有些“死角”在不同的编译器里都有不同的表现,所以我实际上是按照VS2005编译器下的原始类型的行为来设计的,而且还不能做到完全一样。不过我觉得有差异的那些“死角”并不是很重要。

       其实我现在贴出来的是一个早先的版本,因为最新的版本还没有经过测试,所以稳定性和正确性还不能得到保证。不过贴出来的这个版本已经完成了我想要的所有功能,新的修改只是在锦上添花。

       整个工程其实只有6个代码文件,相当少了,当然没包括测试用的代码:

               HugeLongNumber.h

               UnsignedHugeLong.h

               SignedHugeLong.h

               HugeNumberBase.h

               Helper.h

               DataAllocation.h

       我从外面的包装代码开始介绍吧。

1.HugeLongNumber.h

——C++——————————————————————————————————

/*

* Copyright (c) 2005 by DoZerg.  ALL RIGHTS RESERVED. 

* Consult your license regarding permissions and restrictions.

*/

#pragma once

#include "UnsignedHugeLong.h"

#include "SignedHugeLong.h"



namespace DoZerg{

    //typedefs:

    typedef UnsignedHugeLong<1>     ulong0;

    typedef UnsignedHugeLong<2>     ulong1;

    typedef UnsignedHugeLong<4>     ulong2;

    typedef UnsignedHugeLong<8>     ulong3;

    typedef UnsignedHugeLong<16>    ulong4;

    typedef UnsignedHugeLong<32>    ulong5;

    typedef UnsignedHugeLong<64>    ulong6;

    typedef UnsignedHugeLong<128>   ulong7;

    typedef UnsignedHugeLong<256>   ulong8;

    typedef UnsignedHugeLong<512>   ulong9;

    typedef UnsignedHugeLong<1024>  ulong10;

    //typedefs:

    typedef SignedHugeLong<1>       slong0;

    typedef SignedHugeLong<2>       slong1;

    typedef SignedHugeLong<4>       slong2;

    typedef SignedHugeLong<8>       slong3;

    typedef SignedHugeLong<16>      slong4;

    typedef SignedHugeLong<32>      slong5;

    typedef SignedHugeLong<64>      slong6;

    typedef SignedHugeLong<128>     slong7;

    typedef SignedHugeLong<256>     slong8;

    typedef SignedHugeLong<512>     slong9;

    typedef SignedHugeLong<1024>    slong10;

    //others:

#define GLOBAL_DEFINE_OPERATOR(oper)    /

    template<long N,class T1,class T2>  /

    inline const UnsignedHugeLong<N,T1> operator ##oper##(const SignedHugeLong<N,T2> & value1,const UnsignedHugeLong<N,T1> & value2){   /

        return UnsignedHugeLong<N,T1>(value2).operator ##oper##=(value1);   /

    }   /

    template<long N,class T1,class T2>  /

    inline const UnsignedHugeLong<N,T1> operator ##oper##(const UnsignedHugeLong<N,T1> & value1,const SignedHugeLong<N,T2> & value2){   /

        return UnsignedHugeLong<N,T1>(value1).operator ##oper##=(value2);   /

    }

    GLOBAL_DEFINE_OPERATOR(+);

    GLOBAL_DEFINE_OPERATOR(-);

    GLOBAL_DEFINE_OPERATOR(*);

    GLOBAL_DEFINE_OPERATOR(/);

    GLOBAL_DEFINE_OPERATOR(%);

#undef GLOBAL_DEFINE_OPERATOR

}//namespace DoZerg

——————————————————————————————————————

这是对类UnsignedHugeLong和SignedHugeLong名字的包装,分别定义成了ulong和slong,表示无符号和有符号整数。

接下来的代码主要是对2者混合运算的处理,参考VS2005的原始整型的行为来定的。

  

2.UnsignedHugeLong.h

——C++——————————————————————————————————

 

/*

 * Copyright (c) 2005 by DoZerg.  ALL RIGHTS RESERVED. 

 * Consult your license regarding permissions and restrictions.

 */

#pragma once

#include "HugeNumberBase.h"



namespace DoZerg{

//For operator +,-,*,/ and % implementation

#define UNSIGNED_MEMBER_DEFINE_OPERATOR(oper)    /

    template<typename __ValueType>    /

        const UnsignedHugeLong operator ##oper##(const __ValueType & value) const{    /

            return UnsignedHugeLong<N,__Alloc>(*this).operator ##oper##=(value);    /

        }    /

    const UnsignedHugeLong operator ##oper##(const UnsignedHugeLong & value) const{    /

        return UnsignedHugeLong<N,__Alloc>(*this).operator ##oper##=(value);    /

    }

#define UNSIGNED_GLOBAL_DEFINE_OPERATOR(oper)    /

    template<typename __ValueType,long N,class T>    /

        inline const UnsignedHugeLong<N,T> operator ##oper##(const __ValueType & value1,const UnsignedHugeLong<N,T> & value2){    /

            return UnsignedHugeLong<N,T>(value1).operator ##oper##=(value2);    /

        }//*/

//declaration.

    template<

        long N,

        template<long,typename>class __Alloc = DataAutoSelect

    >class UnsignedHugeLong:public HugeNumberBase<N,__Alloc>

    {

    public:

        UnsignedHugeLong(){}

        template<typename __ValueType>

            UnsignedHugeLong(const __ValueType & value):HugeNumberBase<N,__Alloc>(value){}

        UnsignedHugeLong & operator =(const std::string &);

        const UnsignedHugeLong operator +() const;

        const UnsignedHugeLong operator -() const;

        const UnsignedHugeLong operator ~() const;

        const UnsignedHugeLong operator >>(long) const;

        const UnsignedHugeLong operator <<(long) const;

        const UnsignedHugeLong & operator ++();

        const UnsignedHugeLong operator ++(int);

        const UnsignedHugeLong & operator --();

        const UnsignedHugeLong operator --(int);

        const UnsignedHugeLong & operator >>=(long);

        const UnsignedHugeLong & operator <<=(long);

        const UnsignedHugeLong & operator +=(const UnsignedHugeLong &);

        const UnsignedHugeLong & operator -=(const UnsignedHugeLong &);

        const UnsignedHugeLong & operator *=(const UnsignedHugeLong &);

        const UnsignedHugeLong & operator /=(const UnsignedHugeLong &);

        const UnsignedHugeLong & operator &=(const UnsignedHugeLong &);

        const UnsignedHugeLong & operator |=(const UnsignedHugeLong &);

        const UnsignedHugeLong & operator ^=(const UnsignedHugeLong &);

        const UnsignedHugeLong & operator %=(const UnsignedHugeLong &);

        bool operator ==(const UnsignedHugeLong &) const;

        bool operator !=(const UnsignedHugeLong &) const;

        const UnsignedHugeLong Power(const UnsignedHugeLong &);

        const std::string ToString(int = 10) const;

        UNSIGNED_MEMBER_DEFINE_OPERATOR(+);

        UNSIGNED_MEMBER_DEFINE_OPERATOR(-);

        UNSIGNED_MEMBER_DEFINE_OPERATOR(*);

        UNSIGNED_MEMBER_DEFINE_OPERATOR(/);

        UNSIGNED_MEMBER_DEFINE_OPERATOR(%);

//friend functions. for several reasons they can't be implemented outside 

        inline friend bool operator >(const UnsignedHugeLong & value1,const UnsignedHugeLong & value2){

            return value1.OperatorLarger(value2);

        }

        inline friend bool operator <(const UnsignedHugeLong & value1,const UnsignedHugeLong & value2){

            return value1.OperatorSmaller(value2);

        }

        inline friend bool operator >=(const UnsignedHugeLong & value1,const UnsignedHugeLong & value2){

            return value1.OperatorNotSmaller(value2);

        }

        inline friend bool operator <=(const UnsignedHugeLong & value1,const UnsignedHugeLong & value2){

            return value1.OperatorNotLarger(value2);

        }

        template<typename __OutStreamType>

            inline friend __OutStreamType & operator <<(__OutStreamType & os,const UnsignedHugeLong & value){

                return os<<value.ToString();

            }

        inline friend std::ostream & operator <<(std::ostream & os,const UnsignedHugeLong & value){

            return os<<value.ToString((0xc00&os.flags())>>7);    //is there a better way to deal with the base(8,10 or16)?

        }

    };

//definition

//public:

    template<long N,template<long,typename>class __Alloc>

        inline UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator =(const std::string & value){

            FromString(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::operator +() const{

            return UnsignedHugeLong<N,__Alloc>(*this);

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::operator -() const{

            return UnsignedHugeLong<N,__Alloc>(*this).Minus();

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::operator ~() const{

            return UnsignedHugeLong<N,__Alloc>(*this).Complement();

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::operator >>(long value) const{

            return UnsignedHugeLong<N,__Alloc>(*this).RightShift(value);

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::operator <<(long value) const{

            return UnsignedHugeLong<N,__Alloc>(*this).LeftShift(value);

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator ++(){        //you could throw "overflow" if you want

            Increase();

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::operator ++(int){

            UnsignedHugeLong<N,__Alloc> tmp(*this);

            operator ++();

            return tmp;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator --(){

            Decrease();

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::operator --(int){

            UnsignedHugeLong<N,__Alloc> tmp(*this);

            operator --();

            return tmp;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator >>=(long value){

            RightShift(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator <<=(long value){

            LeftShift(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator +=(const UnsignedHugeLong & value){

            OperatorAdd(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator -=(const UnsignedHugeLong & value){

            OperatorSub(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator *=(const UnsignedHugeLong & value){

            OperatorMult(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator /=(const UnsignedHugeLong & value){

            OperatorDiv(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator &=(const UnsignedHugeLong & value){

            OperatorAnd(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator |=(const UnsignedHugeLong & value){

            OperatorOr(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator ^=(const UnsignedHugeLong & value){

            OperatorXor(value);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> & UnsignedHugeLong<N,__Alloc>::operator %=(const UnsignedHugeLong & value){

            OperatorDiv(value,false);

            return *this;

        }

    template<long N,template<long,typename>class __Alloc>

        inline bool UnsignedHugeLong<N,__Alloc>::operator ==(const UnsignedHugeLong & value) const{

            return OperatorEqual(value);

        }

    template<long N,template<long,typename>class __Alloc>

        inline bool UnsignedHugeLong<N,__Alloc>::operator !=(const UnsignedHugeLong & value) const{

            return !operator ==(value);

        }

    template<long N,template<long,typename>class __Alloc>

        inline const UnsignedHugeLong<N,__Alloc> UnsignedHugeLong<N,__Alloc>::Power(const UnsignedHugeLong & value){

            return UnsignedHugeLong<N,__Alloc>(*this).OperatorPower(value);

        }

    template<long N,template<long,typename>class __Alloc>

        inline const std::string UnsignedHugeLong<N,__Alloc>::ToString(int BaseValue) const{

            return HugeNumberBase<N,__Alloc>::ToString(BaseValue);

        }

//others:

    template<typename __ValueType,long N,class __Alloc>

        inline bool operator ==(const __ValueType & value1,const UnsignedHugeLong<N,__Alloc> & value2){

            return value2.operator ==(value1);

        }

    template<typename __ValueType,long N,class __Alloc>

        inline bool operator !=(const __ValueType & value1,const UnsignedHugeLong<N,__Alloc> & value2){

            return value2.operator !=(value1);

        }

    UNSIGNED_GLOBAL_DEFINE_OPERATOR(+);

    UNSIGNED_GLOBAL_DEFINE_OPERATOR(-);

    UNSIGNED_GLOBAL_DEFINE_OPERATOR(*);

    UNSIGNED_GLOBAL_DEFINE_OPERATOR(/);

    UNSIGNED_GLOBAL_DEFINE_OPERATOR(%);

#undef UNSIGNED_MEMBER_DEFINE_OPERATOR

#undef UNSIGNED_GLOBAL_DEFINE_OPERATOR

}    //namespace DoZerg

——————————————————————————————————————

这段代码要说的内容就多一些了。

首先UnsignedHugeLong是表示无符号大整数的类模版,模版参数有2个:

    long N,

    template<long,typename>class __Alloc

前者N表示大整数内部有多少个long的数据,也就能表示2^(32 * N)以内的整数。

后者__Alloc是表示内部的long数组采用哪种存储方式,具体可选的的类定义在DataAllocation.h中,后面会讲道。

UnsignedHugeLong主要的工作就是对运算符进行重载,从代码里可以看出来,它基本上都是调用基类HugeNumberBase的Operator...函数来完成实际的运算。

UnsignedHugeLong还有一个重要的任务,就是对各种原始数据类型的兼容,这曾经是我很头疼的问题之一。代码中的那些可恶的宏基本上就是完成这部分工作的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值