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; //initialize as 0
uint len; //initialize as 0
int sign; //initialize as 0 ; 0: positive; 1: negative
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=num%BASE;
num/=BASE;
}
}
this(char num){
if(num.length==0) {len=1;return;}
int beg=0;
switch(num){
case '-': {sign=1;}
case '+': {++beg;}
default : break;
}
int i=num.length-BASELEN;
for(;i>=beg;i-=BASELEN){
char tmp=num;
data=atoi(tmp);
}
i+=BASELEN;
if(i>beg){
char tmp=num;
data=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>r.data)
return 1;
else if(l.data<r.data) 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= (data+l.data+tmp)%BASE;
tmp = (data+l.data+tmp)/BASE;
}
void residual(uint len,uint data){
for(;i<len;i++){
ret.data=(tmp+data)%BASE;
tmp = (tmp+data)/BASE;
}
}
if(i<len)
residual(len,data);
else if(i<l.len)
residual(l.len,l.data);
ret.len=i;
if(tmp) ret.data=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+tmp;
tmp=(t>big.data);
ret.data=(BASE&(-tmp))+big.data-t;
}
for(;i<big.len;i++){
uint t=tmp;
tmp=(t>big.data);
ret.data=(BASE&(-tmp))+big.data-t;
}
while(ret.data==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+data*l.data+tmp)/BASE;
//writefln(data,",",l.data," ",data*l.data);
ret.data=(ret.data+data*l.data+tmp)%BASE;
tmp=c;
}
}
if(tmp)
ret.data=tmp;
while(ret.data==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);
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=j;
tmp=(tmp-c2+l);
}
while(ret.data==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=data;
for(;i<len;i++)data=0;
len-=s;
return this;
}
ZDNum opShlAssign(uint s){
assert(len+s<MAX);
int i;
for(i=len-1;i>=0;i--)
data=data;
for(i=0;i<s;i++) data=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)~",";
}
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=i;
a=b*a;
}
int time1=GetTickCount()-time0;
writefln(a);
writefln(" time: ",time1);
return 1;
}
--
※作者已于 2005-01-19 14:32:27 修改本文※
|