枫林在线论坛精华区>>程序设计
[323345] 主题: D语言大数类
作者: little (渺小·Happy^_^)
标题: D语言大数类[转载]
来自: 192.168.*.*
发贴时间: 2005年01月19日 14:31:18
长度: 7774字

import std.stdio;
import std.string;
import std.math;
import std.c.windows.windows;

class ZDNum
{
public:
    enum{BASELEN=5,BASE=100000};
    enum{MAX=20000};      //i'm thinking change this to dynamic 
array if 
possible....
    uint data[MAX];   //initialize as 0
    uint len;         //initialize as 0 
    int  sign;        //initialize as 0   ; 0: positive; 1: nega
tive
    this (ZDNum l){
        Assign(l);
    }
    void Assign(ZDNum l)
    {
        len=l.len;
        sign=l.sign;
        data[]=l.data[];
    }
    this(int num=0){                
        if(num==0){len=1;return;}
        if(num<0){
            sign=1;
            num=-num;
        }       
        while(num>0){           
            data[len++]=num%BASE;
            num/=BASE;
        }
    }
    
    this(char[] num){       
        if(num.length==0) {len=1;return;}
        int beg=0;      
        switch(num[0]){
        case '-': {sign=1;}
        case '+': {++beg;}
        default : break;
        }
        int i=num.length-BASELEN;
        for(;i>=beg;i-=BASELEN){    
            char[] tmp=num[i..i+BASELEN];
            data[len++]=atoi(tmp);
        }
        i+=BASELEN;
        if(i>beg){
            char[] tmp=num[0..i];
            data[len++]=atoi(tmp);
        }       
    }
    
    ZDNum opNeg()
    {
        ZDNum ret = new ZDNum(this);
        ret.sign^=1;
        return ret;
    }
        
    int opEquals(ZDNum l){
        if(sign!=l.sign||len!=l.len) return 0;
        return data==l.data;        
    }
    
    
    
    int absCmp(ZDNum l, ZDNum r){
        if(l.len>r.len) return 1;
        else if(l.len<r.len) return 0;      
        
        for(int i=l.len-1;i>=0;i--){
            if(l.data[i]>r.data[i])
                return 1;
            else if(l.data[i]<r.data[i]) return 0;
        }
        return 0;       
    }
    
    int opCmp(ZDNum l)
    {
        if(sign<l.sign) return 1;
        else if(sign>l.sign) return 0;      
        if(sign==0) return absCmp(this,l);
        else return 1&absCmp(l,this);               
    }
        
    
    ZDNum opAdd(ZDNum l)
    {                               
        if(sign!=l.sign){
            l.sign^=1;
            ZDNum ret = this-l;
            l.sign^=1;
            return ret;
        }           
        ZDNum ret=new ZDNum();
        ret.sign = sign;
        uint tmp=0;     
        uint i;
        for(i=0;i<l.len&&i<len;i++){
            ret.data[i]= (data[i]+l.data[i]+tmp)%BASE;
            tmp = (data[i]+l.data[i]+tmp)/BASE;         
        }       
        void residual(uint len,uint data[]){
            for(;i<len;i++){
                ret.data[i]=(tmp+data[i])%BASE;
                tmp = (tmp+data[i])/BASE;                       
    
            }
        }
        if(i<len)
            residual(len,data);                             
        else if(i<l.len)
            residual(l.len,l.data);
        ret.len=i;      
        if(tmp) ret.data[ret.len++]=tmp;        
        return ret;     
    }
        
    ZDNum opSub(ZDNum l)
    {                                
        if(sign!=l.sign){
            l.sign^=1;
            ZDNum ret=this+l;   
            l.sign^=1;
            return ret;
        }
        ZDNum big,small;
        ZDNum ret=new ZDNum();
        ZDNum absSub(ZDNum big,ZDNum small){  //assume big > 
small          
            int tmp=0;
            uint i;         
            ret.len=big.len;
            for(i=0;i<small.len&&i<big.len;i++){  
          
                uint t = small.data[i]+tmp;
                tmp=(t>big.data[i]);
                ret.data[i]=(BASE&(-tmp))+big.data[i]-t;
            }                   
            for(;i<big.len;i++){
                uint t=tmp;
                tmp=(t>big.data[i]);
                
ret.data[i]=(BASE&(-tmp))+big.data[i]-t;                    
    
            }
            while(ret.data[ret.len-1]==0&&ret.len>1) 
ret.len--;     
            return ret;
        }                   
        if(absCmp(this,l)){         
            big=this;small=l;
            ret.sign = sign;
        }else{          
            small=this;big=l;
            ret.sign = sign^1;
        }                                               
        return absSub(big,small);
    }
        
    ZDNum opMul(ZDNum l){
        ZDNum ret = new ZDNum;
        ret.sign = (l.sign^sign);
        ret.len=(len+l.len-1);
        uint tmp=0;
        
        for(uint i=0;i<len;i++){
            for(int j=0;j<l.len;j++){
                int c;              
                c=(ret.data[i+j]+data[i]*l.data[j]+tmp)/BASE;
                //writefln(data[i],",",l.data[j],"
; ",data[i]*l.data[j]);
                
ret.data[i+j]=(ret.data[i+j]+data[i]*l.data[j]+tmp)%BASE;       
        
                tmp=c;
            }           
        }               
        if(tmp)
            ret.data[ret.len++]=tmp;
        while(ret.data[ret.len-1]==0&&ret.len>1) ret.
len--; 
        return ret;
    }
        
    ZDNum opDiv(ZDNum l){
        ZDNum ret = new ZDNum;
        if(len<l.len) return ret;       
        ret.sign = (l.sign^sign);       
        ret.len=len-l.len+1;
        ZDNum tmp=new ZDNum(this);      
        tmp>>=(len-l.len+1);        
        int i=len-l.len;
        for(;i>=0;i--){
            tmp<<=1;            
            tmp=tmp+new ZDNum(data[i]);
            ZDNum c2=new ZDNum(l);
            int j=1;
            for(;c2<=tmp && j<BASE;j++,c2=c2+l){};
 //very low 
efficiency,use binary search will be better
            j--;
            ret.data[i]=j;                      
            tmp=(tmp-c2+l);         
        }
        while(ret.data[ret.len-1]==0&&ret.len>1) ret.
len--; 
        return ret;
    }
    
    
    ZDNum opAddAssign(ZDNum l)
    {
        ZDNum tmp = this + l;
        Assign(tmp);
        return this;
    }
    
    ZDNum opSubAssign(ZDNum l)
    {
        ZDNum tmp = this - l;
        Assign(tmp);
        return this;
    }
    
    ZDNum opMulAssign(ZDNum l)
    {
        ZDNum tmp = this * l;
        Assign(tmp);
        return this;
    }
    ZDNum opDivAssign(ZDNum l)
    {
        ZDNum tmp = this / l;
        Assign(tmp);
        return this;
    }
    ZDNum opShr(uint s)
    {
        ZDNum ret = new ZDNum(this);
        ret>>=s;
        return ret;
    }
    
    ZDNum opShrAssign(uint s){
        uint i;
        for(i=0;i<(len-s);i++)
            data[i]=data[i+s];      
        for(;i<len;i++)data[i]=0;
        len-=s;
        return this;
    }
        
    ZDNum opShlAssign(uint s){
        assert(len+s<MAX);
        int i;                      
        for(i=len-1;i>=0;i--)       
            data[i+s]=data[i];      
        for(i=0;i<s;i++) data[i]=0;
        len+=s;
        return this;
    }
    
    ZDNum opShl(uint s)
    {
        ZDNum ret = new ZDNum(this);
        ret<<=s;
        return ret;
    }
    
    char[] toString(){
        char[] ret;
        if(sign) ret~="-";
        else     ret~="+";
        for(int i=len-1;i>=0;i--){
            ret~= .toString(data[i])~",";
        }
        ret~= "BASE:"~.toString(BASE);
        return ret;     
    }
}

int main(char[][] args)
{
    int time0=GetTickCount();
    ZDNum a = new ZDNum(1); //136780142
    ZDNum b = new ZDNum(1);     
    
    for(int i=2;i<=20000;i++){      
        b.len=1;
        b.data[0]=i;
        a=b*a;  
    }
    int time1=GetTickCount()-time0;
    writefln(a);    
    writefln(" time: ",time1);
    
    return 1;
}
 


--
※作者已于 2005-01-19 14:32:27 修改本文※

========== * * * * * ==========
返回