最近群里有人聊N! (N<=100) 于是发现这种代码的复用还是有点意义的,于是把自己曾经写的一个numberSystem子库公布下。


它能够实现任意精度的带小数位在任意进制下的任意加减乘除余等等。

自从写BinaryTree泛化类采用down-up原语设计后,我就一直喜欢在写内聚性很强的东西时,从元操作(原语)开始实现,之后其他所有之上的操作都能通过几个原语的组合实现。所以能够避免混乱的代码结构和浪费大量调试时间。


/*numberSystem.cpp :vgl::numberSystem*/
/*----------------------------------------------------------------------------
Simple v1.2
Developer: Zblc
vgl::numberSystem

classes:
    numberSystem                            :大数类
                                        

macros:
    BigReal(STR)                            :临时测试用大数对象

global variable:
    numberSystem VGL_G_TEMP;                :临时传递用对象
    char VGL_G_TEMP_STR[MAX_DIGIT];         :临时传递用字符串

include:
    base.h                                  :VGL基库
    string.h                                :VGL泛型字符串库 
--------------------------- --------------------------------------------------
*/





#ifndef NUMBERSYSTEM__
#define NUMBERSYSTEM__


#include 
"base.h"
#include 
"string.h"
#define MAX_DIGIT 500


#define BigReal(STR)  (*(numberSystem*)( new numberSystem(STR)) )



class numberSystem
{

private:
    
int radix;
    
int num[MAX_DIGIT];
    
int len;
    
char sign;
    
int decNum;//decreasing Digit till dot
    void init(int Radix=10);
    
void init(int *Num,int Len=0,int Radix=10,int DecNum=-1);
    
void init(char *Num,int Len=0,int Radix=10);
    
void addFrontZero(numberSystem& obj,int Num);
    
void addBackZero(numberSystem& obj,int Num);
    
void delFrontZero(numberSystem & obj);
    
void delBackZero(numberSystem& obj);
    
void balanceNumber(numberSystem& First,numberSystem& Second);
    
void cleanNumber(numberSystem& Obj);
    
    
void addStrict(numberSystem & Right,numberSystem & Result);
    
void subtractStrict(numberSystem & Right,numberSystem & Result);
    
void mulStrict(int Factor,numberSystem & Result);
    
int getMaxFactor(numberSystem& Obj,numberSystem& Multi);
    
int smallerThanAsInt(numberSystem& Copy);
    
public:
    numberSystem();
    numberSystem(
int Radix);
    numberSystem(
int *Num,int Len=0,char Sign='+',int DecNum=-1,int Radix=10);
    numberSystem(
char *Num,int Len=0,char Sign='+',int Radix=10);
    
void add(numberSystem & Right,numberSystem & Result);
    
void sub(numberSystem & Right,numberSystem & Result);
    
void mul(numberSystem & Right,numberSystem & Result);
    
void div(numberSystem & Right,numberSystem & Result);
    
void mod(numberSystem & Right,numberSystem & Result);

    
    
char getSign();
    
int getLen();
    
int* getNum();
    
char* toChars();
    adt::
string toString();
    numberSystem getInteger();
    numberSystem getDecimal();
    
    
    
int* operator ()();
    
int& operator[](int i);
    
int operator > (numberSystem& Copy);
    
int operator >= (numberSystem& Copy);
    
int operator <= (numberSystem& Copy);
    
int operator < (numberSystem& Copy);
    
int operator == (numberSystem& Copy);
    
int operator == (char* strNum);
    numberSystem 
operator +(numberSystem& Right);
    numberSystem 
operator +=(numberSystem& Right);

    numberSystem 
operator -(numberSystem& Right);
    numberSystem 
operator -=(numberSystem& Right);

    numberSystem 
operator *(numberSystem& Right);
    numberSystem 
operator *=(numberSystem& Right);

    numberSystem 
operator /(numberSystem& Right);
    numberSystem 
operator /=(numberSystem& Right);

    numberSystem 
operator %(numberSystem& Right);
    numberSystem 
operator %=(numberSystem& Right);

    numberSystem
& operator=(const numberSystem& Copy);

    
}
;


#endif




#include "numberSystem.h"

numberSystem VGL_G_TEMP;
char VGL_G_TEMP_STR[MAX_DIGIT];
numberSystem numberSystem::
operator +(numberSystem& Right)
{
    add(Right,VGL_G_TEMP);
    
return VGL_G_TEMP;
}

numberSystem numberSystem::
operator +=(numberSystem& Right)
{
    add(Right,
*this);
    
return *this;
}

numberSystem numberSystem::
operator -(numberSystem& Right)
{
    sub(Right,VGL_G_TEMP);
    
return VGL_G_TEMP;
}

numberSystem numberSystem::
operator -=(numberSystem& Right)
{
    sub(Right,
*this);
    
return *this;
}

numberSystem numberSystem::
operator *(numberSystem& Right)
{
    mul(Right,VGL_G_TEMP);
    
return VGL_G_TEMP;
}

numberSystem numberSystem::
operator *=(numberSystem& Right)
{
    mul(Right,
*this);
    
return *this;
}

numberSystem numberSystem::
operator /(numberSystem& Right)
{
    div(Right,VGL_G_TEMP);
    
return VGL_G_TEMP;
}

numberSystem numberSystem::
operator /=(numberSystem& Right)
{
    div(Right,
*this);
    
return *this;
}

numberSystem numberSystem::
operator %(numberSystem & Right)
{
    mod(Right,VGL_G_TEMP);
    
return VGL_G_TEMP;
}

numberSystem numberSystem::
operator %=(numberSystem & Right)
{
    mod(Right,
*this);
    
return *this;
}

void numberSystem::init(int Radix/*=10*/)
{
    decNum
=-1;
    radix
=Radix;
}

void numberSystem::init(int *Num,int Len/*=0*/,int Radix/*=10*/,int DecNum/*=-1*/)
{
    decNum
=DecNum;
    radix
=Radix ;
    
if(!Len)
        
for(;Num[Len]<=-1;Len++);
    
else if(Len<0)
        TEST_THROW(
"numberSystem::init(..)")
        len
=Len;
    
for(;Len!=0;Len--)
        num[Len
-1]=Num[Len-1];
}

void numberSystem::init(char *Num,int Len/*=0*/,int Radix/*=10*/)
{
    decNum
=-1;
    radix
=Radix ;
    
if(!Len)
        
for(;Num[Len]!='\0';Len++);
    
else if(Len<0)
        TEST_THROW(
"numberSystem::init(..)")
        len
=Len;

    
int k=0,j=0,tag=0;
    
if(Num[0]=='+')
        sign
='+',Num++,tag=1,len--;
    
else if(Num[0]=='-')
        sign
='-',Num++,tag=1,len--;

    Len
-=tag;
    
for(;j!=Len;j++)
        
if(Num[j]!='.')
        
{
            num[k]
=Num[j]-48;
            k
++;
        }
else
        
{
            decNum
=j;
            len
--;
        }

    
if(decNum==-1)
        decNum
=len;

}

void numberSystem::addFrontZero(numberSystem& obj,int Num)
{
    
for(int i=obj.len+Num-1;i!=Num-1;i--)
        obj.num[i]
=obj.num[i-Num];

    
for(int i=0;i!=Num;i++)
        obj.num[i]
=0;

    obj.decNum
+=Num;
    obj.len
+=Num;
}

void numberSystem::addBackZero(numberSystem& obj,int Num)
{
    
for(int i=0;i!=Num;i++)
        obj.num[i
+obj.len]=0;
    obj.len
+=Num;

}

void numberSystem::delFrontZero(numberSystem & obj)
{
    
if(obj.len==1||(obj.decNum==1))
        
return;

    
int k=0;
    
for(;(k!=obj.len)&&(obj.num[k]==0)&&(k!=obj.decNum);k++);


    
if(k==obj.decNum)
        k
--;
    
for(int i=0;i!=obj.len-k;i++)
        obj.num[i]
=obj.num[i+k];

    
if(k==obj.len)
    
{

        obj.num[
0]=0;
        
--k;
    }


    obj.len
-=k;
    
if(obj.decNum>0)
        obj.decNum
-=k;

}

void numberSystem::delBackZero(numberSystem& obj)
{
    
int i=obj.len-1;
    
for(;;i--)
    
{
        
if(obj.num[i]==0&&i>obj.decNum-1)
            obj.len
--;
        
else
            
return;
    }

}

void numberSystem::balanceNumber(numberSystem& First,numberSystem& Second)
{
    
if(First.decNum>Second.decNum)
    
{
        addFrontZero(Second,First.decNum
-Second.decNum);
    }

    
else if(First.decNum<Second.decNum)
    
{
        addFrontZero(First,Second.decNum
-First.decNum);
    }



    
if(First.len-First.decNum>Second.len-Second.decNum)
    
{
        addBackZero(Second,(First.len
-First.decNum)-(Second.len-Second.decNum));
    }

    
else if(First.len-First.decNum<Second.len-Second.decNum)
    
{

        addBackZero(First,(Second.len
-Second.decNum)-(First.len-First.decNum));
    }

}

void numberSystem::cleanNumber(numberSystem& Obj)
{
    delFrontZero(Obj);
    delBackZero(Obj);
}


void numberSystem::addStrict(numberSystem & Right,numberSystem & Result)
{
    
if(radix!=Right.radix)
        TEST_THROW(
"numberSystem:operands differed in radix");

    numberSystem First
=*this,Second=Right;
    
int i,carry=0;

    balanceNumber(First,Second);

    i
=First.len;
    Result.init(radix);
    Result.decNum
=First.decNum+1;
    Result.len
=i+1;

    
for(;i!=0;i--)
    
{
        Result.num[i]
=(carry+First[i-1]+Second[i-1])%radix;
        carry
=(carry+First[i-1]+Second[i-1])/radix;
    }


    Result[i]
=carry;
    cleanNumber(Result);

}

void numberSystem::subtractStrict(numberSystem & Right,numberSystem & Result)
{
    
if(radix!=Right.radix)
        TEST_THROW(
"numberSystem:operands differed in radix");

    numberSystem First
=*this,Second=Right;

    
int i,carry=0;

    balanceNumber(First,Second);

    
if(First.smallerThanAsInt(Second))
    
{
        atom::swap(First,Second);
        Result.sign
='-';
    }
else
    
{
        Result.sign
='+';
    }


    i
=First.len-1;
    Result.init(radix);
    Result.decNum
=First.decNum;
    Result.len
=i+1;

    
for(;i!=-1;i--)
        
if(First[i]+carry>=Second[i])
        
{
            Result.num[i]
=First[i]-Second[i]+carry;
            carry
=0;
        }
else
        
{
            Result.num[i]
=radix-Second[i]+First[i]+carry;
            carry
=-1;
        }

    cleanNumber(Result);

}

void numberSystem::mulStrict(int Factor,numberSystem & Result)
{
    Result.init(radix);
    
int carry=0,i=len-1,j=len;
    
for(;i!=-1;i--,j--)
    
{
        Result.num[j]
=(num[i]*Factor+carry)%radix;

        carry
=(num[i]*Factor+carry)/radix;
    }

    Result.num[j]
=carry;
    Result.len
=len+1;
    Result.decNum
=Result.len;
    delFrontZero(Result);    
}



int numberSystem::getMaxFactor(numberSystem& Obj,numberSystem& Multi)
/* Obj>=Multi*MAX(Result) */
{
    
if(Obj.radix!=Multi.radix)
        TEST_THROW(
"numberSystem: in getMaxFactor radixes differ ");
    numberSystem _temp(Obj.radix);
    
for(int i=9;i!=-1;i--)
    
{
        Multi.mulStrict(i,_temp);

        
if(!Obj.smallerThanAsInt(_temp))
        
{
            
return i;
        }

    }

    
return 0;
}


numberSystem::numberSystem():radix(
10),len(0),sign('+')
{
}

numberSystem::numberSystem(
int Radix):radix(Radix),len(0),sign('+')
{
}

numberSystem::numberSystem(
int *Num,int Len/*=0*/,char Sign/*='+'*/,int DecNum/*=-1*/,int Radix/*=10*/)
:radix(Radix),sign(Sign)
{
    init(Num,Len,Radix,DecNum);
}

numberSystem::numberSystem(
char *Num,int Len/*=0*/,char Sign/*='+'*/,int Radix/*=10*/)
:radix(Radix),sign(Sign)
{
    init(Num,Len,Radix);
}

void numberSystem::add(numberSystem & Right,numberSystem & Result)
{
    
if(sign=='+')
    
{
        
if(Right.sign=='+')
        
{
            addStrict(Right,Result);

        }
else
        
{
            subtractStrict(Right,Result);
        }

    }
else if(sign=='-')
    
{
        
if(Right.sign=='+')
        
{
            Right.subtractStrict(
*this,Result);

        }
else
        
{
            addStrict(Right,Result);
            Result.sign
='-';
        }

    }


}

void numberSystem::sub(numberSystem & Right,numberSystem & Result)
{
    
if(sign=='+')
    
{
        
if(Right.sign=='+')
        
{
            subtractStrict(Right,Result);
        }
else
        
{
            addStrict(Right,Result);
        }

    }
else if(sign=='-')
    
{
        
if(Right.sign=='+')
        
{
            addStrict(Right,Result);
            Result.sign
='-';
        }
else
        
{
            Right.subtractStrict(
*this,Result);
        }

    }


}

void numberSystem::mul(numberSystem & Right,numberSystem & Result)
{
    numberSystem First
=*this,Second=Right;
    Result.init(
"0");
    numberSystem _temp(
"0"),_temp2("0");
    
int Decimal=First.len+Second.len-First.decNum-Second.decNum;


    
int dig=0;
    
for(int i=Second.len-1;i!=-1;i--,dig++){
        First.mulStrict(Second.num[i],_temp);

        
for(int j=0;j!=dig;j++)
        
{
            _temp.num[_temp.len
++]=0;
            _temp.decNum
++;
        }

        _temp.add(_temp2,_temp2);

    }

    Result
=_temp2;
    Result.decNum
=Result.len-Decimal;
    cleanNumber(Result);
    
if(sign==Right.sign)
    
{
        Result.sign
='+';
    }
else
    
{
        Result.sign
='-';
    }


}

void numberSystem::div(numberSystem & Right,numberSystem & Result)
{
    
if(sign==Right.sign) Result.sign='+';
    
else Result.sign='-';
    
if(Right=="0")
        TEST_THROW(
"numberSystem: in div divisor is zero ");
    
if((*this)=="0"){
        Result
=(*this);
        
return ;
    }

    numberSystem First
=*this,Second=Right,_temp(radix),_temp2("10");
    
int i=0,j=0,k=max(len-decNum,Right.len-Right.decNum);
    Result.init(
"");

    
for(int t=0;t!=k;t++){
        First.mul(_temp2,First);
        Second.mul(_temp2,Second);
    }

    
for(;Result.len!=MAX_DIGIT;){
        
for(int s=0;_temp.smallerThanAsInt(Second);s++){
            _temp.num[_temp.len
++]=First.num[i++];
            
if(s>0){
                Result.num[Result.len
++]=0;
                
if(i-1<=First.len)
                    Result.decNum
++;
            }
            
            
if(i>=First.len) First.num[i]=0;
            _temp.decNum
=_temp.len;
            cleanNumber(_temp);
            
if(_temp=="0"break;
        }

        i
<=First.len?Result.decNum++:1;
        Result.num[Result.len
++]=getMaxFactor(_temp,Second);
        Second.mulStrict(Result.num[Result.len
-1],_temp2);
        _temp.sub(_temp2,_temp);
        
if((_temp=="0")&&(i>=First.len))
            
break;
    }

    cleanNumber(Result);

}


int* numberSystem::operator ()()
{
    
return num;
}

int* numberSystem::getNum()
{
    
return num;
}

int& numberSystem::operator[](int i)
{
    
return num[i];
}


int numberSystem::getLen()
{
    
return len;
}

char numberSystem::getSign()
{
    
return sign;
}

numberSystem
& numberSystem::operator=(const numberSystem& Copy)
{
    sign
=Copy.sign;
    len
=Copy.len;
    radix
=Copy.radix;
    decNum
=Copy.decNum;

    
for(int i=0;i!=Copy.len;i++)
        num[i]
=Copy.num[i];

    
return *this;
}

int numberSystem::operator > (numberSystem& Copy)
{
    
if(radix!=Copy.radix)
        TEST_THROW(
"numberSystem: in operator <  radixes differ ");

    
if(*this==Copy)
        
return 0;
    
return (*this-Copy).sign=='+'?1:0;
}

int numberSystem::operator >= (numberSystem& Copy)
{
    
return !(*this<Copy);
}

int numberSystem::operator <= (numberSystem& Copy)
{
    
return !(*this>Copy);
}

int numberSystem::operator < (numberSystem& Copy)
{
    
if(radix!=Copy.radix)
        TEST_THROW(
"numberSystem: in operator <  radixes differ ");

    
if(*this==Copy)
        
return 0;
    
return (*this-Copy).sign=='+'?0:1;
}

int numberSystem::smallerThanAsInt(numberSystem& Copy)
{
    
if(len<Copy.len)
        
return 1;
    
else if(len>Copy.len)
        
return 0;

    
for(int i=0;i!=len;i++)
        
if(num[i]<Copy.num[i])
            
return 1;
        
else if(num[i]>Copy.num[i])
            
return 0;

    
return 0;
}

int numberSystem::operator == (numberSystem& Copy)
{
    
if(radix!=Copy.radix)
        TEST_THROW(
"numberSystem: in operator ==  radixes differ ");

    
if(len!=Copy.len)
        
return 0;

    
if(sign!=Copy.sign)
        
return 0;

    
for(int i=0;i!=len;i++)
        
if(num[i]!=Copy.num[i])    
            
return 0;

    
return 1;
}

int numberSystem::operator == (char* strNum)
{
    VGL_G_TEMP.init(strNum);
    
return VGL_G_TEMP==*this;
}


char* numberSystem::toChars()
{
    adt::
string _temp=toString();
    
for(int i=0;i!=_temp.len;i++)
        VGL_G_TEMP_STR[i]
=_temp[i];
    
return VGL_G_TEMP_STR;

}

adt::
string numberSystem::toString()
{
    adt::
string _temp;
    
if(sign=='-')
        _temp
<<'-';
    
for(int i=0;i!=len;i++)
        
if(decNum!=i)
            _temp
<<(char)(num[i]+48);
        
else
            _temp
<<'.'<<(char)(num[i]+48);
    _temp
<<(char)0;
    
return _temp;
}



numberSystem numberSystem::getInteger()
{
    VGL_G_TEMP
=*this;
    VGL_G_TEMP.len
=VGL_G_TEMP.decNum;
    VGL_G_TEMP.sign
='+';
    
return VGL_G_TEMP;
}

numberSystem numberSystem::getDecimal()
{
    
return *this-getInteger();
}


void numberSystem::mod(numberSystem & Right,numberSystem & Result)
{
    
if(this->len!=this->decNum||Right.len!=Right.decNum)
        TEST_THROW(
"numberSystem: in function mod  ,the legal number appears");
    numberSystem First
=*this,Second=Right;
    First.sign
='+';
    Second.sign
='+';
    Result
=First-(((First)/Second).getInteger())*Second;
    Result.sign
=(this->sign==Right.sign)?'+':'-';
}



关于case 就不发了,想执行的可以留言,因为还涉及到公共基础子库的引入.