/* * 作用:把ln a乘以int b * 副作用:调用ln_stripleadingzero()消除a前置0并且用ln_stripendingzero()调整a的指数 * 副作用:调用ln_stripleadingzero()消除结果的前置0 * 参数: * a:待相乘的ln * b:待相乘的int * restype:结果存放方式 * 返回值: * 成功:返回相加结果 * 失败:NULL */ ln ln_multiply_int(ln a,int b,res_type restype) { ln c,d; //验证参数 if(ln_checknull(a)!=0) { fprintf(stderr,"[%s %d] %s error,reason: ln_checknull fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //去除前置0 ln_stripleadingzero(a); //简单地去掉后置0 ln_stripendingzero(a); //把int转换为ln c=ln_init(b); if(c==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_init fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //相乘 d=ln_multiply(a,c,restype); if(d==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_multiply fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } ln_free(&c); return d; }
int main() { int i,b; ln sum=ln_init(1); ln k=NULL; ln temp=NULL; ln j=ln_init(1); i=2; b=7830457; j->lowestdigit->digit=i; j->highestdigit=j->lowestdigit; k=ln_init(i); b--; while(1) { temp=copy_largenums(temp,j); multiply_largenums(j,temp,firstnumber); if(get_digitnum(j)>10) ln_truncate(j,3); b/=2; if(b==1) break; if(b%2!=0) { multiply_largenums(k,j,firstnumber); b--; } } free_largenum(temp); multiply_largenums(k,j,firstnumber); j=largenum_setval(j,28433); multiply_largenums(k,j,firstnumber); add_largenums(sum,k,firstnumber); show_largenum(sum); return 0; }
//get the numerator part of the num in base b and converted to base 10 ln get_numerator(const char* num,int b) { const char*p; ln numerator; ln base; ln add_digit; numerator=ln_init(0); base=ln_init(1); p=num+strlen(num)-1; while(p>=num) { if(*p !='.') { add_digit=ln_multiply_int(base,*p-'0',newln); ln_add(numerator,add_digit,firstln); ln_free(&add_digit); ln_multiply_int(base,b,firstln); } p--; } return numerator; }
//get the denominator part of the num in base b and converted to base 10 ln get_denominator(const char* num,int b) { const char*p; ln denominator; denominator=ln_init(1); p=strstr(num,"."); if(p) //has fractional part { p++; while(*p) { ln_multiply_int(denominator,b,firstln); p++; } } return denominator; }
/* * 作用:比较ln a和int b的大小 * 副作用:使用ln_stripleadingzero()把a整数部分前置0去掉 * 参数: * a:待比较的ln * b:待比较的int * 返回值: * 0: a=b * 1: a>b * -1: a<b * -2: 出错 */ int ln_cmp_int(ln a,int b) { int res; ln c; //检查参数 if(ln_checknull(a)!=0) { fprintf(stderr,"[%s %d] %s error,reason: ln_checknull fail\n",__FILE__,__LINE__,__FUNCTION__); return -2; } c=ln_init(b); if(c==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_init fail\n",__FILE__,__LINE__,__FUNCTION__); return -2; } res=ln_cmp(a,c); ln_free(&c); return res; }
/* * 作用:把ln a加上int b * 副作用:调用ln_stripleadingzero()消除a前置0并且用ln_adjustpower()调整a的指数 * 副作用:调用ln_stripleadingzero()消除结果的前置0 * 参数: * a:待相加的ln * b:待相加的int * restype:结果存放方式 * 返回值: * 成功:返回相加结果 * 失败:NULL */ ln ln_add_int(ln a,int b,res_type restype) { ln c,d; //验证参数 if(ln_checknull(a)!=0) { fprintf(stderr,"[%s %d] %s error,reason: ln_checknull fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } c=ln_init(b); if(c==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_init fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } d=ln_add(a,c,restype); ln_free(&c); return d; }
int can_go(Pair* p){ Pair *b = bts; Pair s, t, md, mv, mh, next, buf1, buf2, buf3; int v, h, ver, hor; /* coordinate steps */ double val; int vis; while(b != bts+2){ ln_init(b,p_get(Z,b)+0.5,p,p_get(Z,p)+0.5); /* go from the bottom up */ if(p_get(Z,p) < p_get(Z,b)){ s = *p; t = *b; }else{ s = *b; t = *p; } hor = (s.c > t.c) ? -1 : 1; ver = (s.r > t.r) ? -1 : 1; #ifdef DEBUG printf("v: %d, h: %d\n",ver,hor); #endif h = (hor>0) ? 0 : 1; v = (ver>0) ? 0 : 1; vis = 1; while(!p_eq(&s,&t)){ md = p_new(ver,hor); md = p_sum(&s,&md); buf1 = p_new(md.r+v,md.c+h); if(ln_rc_val(&buf1)==0){ val = ln_z_by_r(buf1.r); next = md; }else{ mv = p_new(ver,0); mv = p_sum(&s,&mv); buf2 = p_new(mv.r+v,mv.c+h); if(!ln_rc_on_same_side(&buf1,&buf2)){ val = ln_z_by_r(buf2.r); next = mv; }else{ mh = p_new(0,hor); mh = p_sum(&s,&mh); buf3 = p_new(mh.r+v,mh.c+h); val = ln_z_by_c(buf3.c); next = mh; } } #ifdef DEBUG printf("next %d,%d\n",next.r,next.c); #endif if(p_get(Z,&next) > val){ #ifdef DEBUG printf("bad p: %d,%d val: %f\n",next.r,next.c,val); #endif vis = 0; break; } s = next; } if(vis) break; ++b; /* take next bts */ } return vis; }
/* * 作用:把ln相除 * 副作用:使用ln_stripleadingzero()把a,b整数部分前置0去掉 * 参数: * a:除数 * b:被除数 * precision:所需精度(保留的小数位数) * mode:指定截断或者四舍五入 * restype:结果存放方式 * 返回值: * 成功:返回相加结果 * 失败:NULL */ ln ln_divide(ln a,ln b,int precision,divide_mode mode,res_type restype) { ln c; ln x,y,z; int x_cellnum; int y_cellnum; int inc_prec=0; //累积精度 cell i,j,k; //验证参数 if(ln_checknull(a)!=0) { fprintf(stderr,"[%s %d] %s error,reason: ln_checknull fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } if(ln_checknull(b)!=0) { fprintf(stderr,"[%s %d] %s error,reason: ln_checknull fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //去除前置0 ln_stripleadingzero(a); ln_stripleadingzero(b); //复制ln x=ln_copy(NULL,a); if(x==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_copy fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } y=ln_copy(NULL,b); if(y==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_copy fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //分配结果空间 z=ln_init(0); if(z==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_init fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //确定符号 if(x->sign==y->sign) z->sign=1; else z->sign=-1; //把x,y整数部分节点数调整一致 x_cellnum=ln_cellnum(x); if(x_cellnum==-1) { fprintf(stderr,"[%s %d] %s error,reason: ln_cellnum fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } y_cellnum=ln_cellnum(y); if(y_cellnum==-1) { fprintf(stderr,"[%s %d] %s error,reason: ln_cellnum fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } if(x_cellnum<y_cellnum) ln_adjustpower(x,(x_cellnum-y_cellnum)*DIGIT_NUM); if(y_cellnum<x_cellnum) ln_adjustpower(y,(y_cellnum-x_cellnum)*DIGIT_NUM); //算出初始精度 inc_prec=ln_pointnum(x,x->lsd)-DIGIT_NUM+y->power; x->sign=1; x->power=0; y->power=0; z->power=0; i=x->msd; j=y->msd; k=z->msd; while(1) { if(i!=x->msd) k->num=(i->num+i->hcell->num*UNIT)/j->num; //求出z位数 else k->num=i->num/j->num; //求出z位数 //printf("addr=%d num=%d\n",(int)k,k->num); if(k->num !=0) { y->sign=-1; //y变成负数 c=ln_multiply_int(y,k->num,newln); ln_add(x,c,firstln); ln_free(&c); while(x->sign==1) //少减了,再减去 { y->sign=-1; ln_add(x,y,firstln); k->num++; } while(x->sign==-1) //多减了,补上 { y->sign=1; ln_add(x,y,firstln); k->num--; } } //开始计算当前精度 inc_prec+=DIGIT_NUM; if(inc_prec>precision) //已经达到需要的精度 { z->lsd=k; //确定指数 z->power=-inc_prec; break; } if(ln_cmp_int(x,0)==0) //除得尽 { z->lsd=k; //确定指数 z->power=-inc_prec; break; } //去掉前置0 if(x->msd->num==0 && x->msd !=x->lsd) x->msd=x->msd->lcell; //增加节点 if(x->lsd->lcell ==x->msd) { if(ln_addcell(x,INIT_SIZE) ==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_addcell fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } } x->lsd=x->lsd->lcell; x->lsd->num=0; i=i->lcell; //增加节点 if(k==z->lsd) { if(ln_addcell(z,INIT_SIZE) ==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_addcell fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } } z->lsd=z->msd->hcell; k=k->lcell; } //释放临时ln ln_free(&x); ln_free(&y); //去除前置0 ln_stripleadingzero(z); //获取精度 ln_fix(z,precision,mode); //复制给a if(restype==firstln) { ln_copy(a,z); ln_free(&z); return a; } else return z; }
/* * 作用:把ln a除以int b * 副作用:调用ln_stripleadingzero()消除a前置0并且用ln_adjustpower()调整a的指数 * 副作用:调用ln_stripleadingzero()消除结果的前置0 * 参数: * a:除数 * b:被除数 * precision:所需精度(保留的小数位数) * mode:指定截断或者四舍五入 * restype:结果存放方式 * 返回值: * 成功:返回相加结果 * 失败:NULL */ ln ln_divide_int(ln a,int b,int precision,divide_mode mode,res_type restype) { //TODO:如果a或者b=MIN_INT 这边会溢出要转换成ln除法 int res=0; int carry=0; int inc_prec=0; //累积精度 ln c,d; cell x,z; //验证参数 if(ln_checknull(a)!=0) { fprintf(stderr,"[%s %d] %s error,reason: ln_checknull fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //精度参数有误 if(precision<0) { fprintf(stderr,"[%s %d] %s error,reason: precision error\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //除数不能为0 if(b==0) { fprintf(stderr,"[%s %d] %s error,reason: b=0\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } //除数必须在-200000-200000之间否则下面计算有可能溢出,因此必须把b转化成ln再操作 //这个范围是根据INT_MAX/UNIT即2147483647/10000得出 if(b>200000 || b<-200000) { d=ln_init(b); if(d==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_init fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } c=ln_divide(a,d,precision,mode,restype); if(c==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_divide fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } return c; } //去除前置0 ln_stripleadingzero(a); //没指定商的精度 那就使用默认精度 if(precision<0) precision=DIV_PREC; if(restype==newln) { c=ln_creat(ln_cellnum(a)); if(c==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_creat fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } c->msd=c->lsd->lcell; } else c=a; //确定符号 if(b>0) c->sign=a->sign; else { c->sign=-a->sign; b=-b; } //算出初始精度 inc_prec=ln_pointnum(a,a->msd)-DIGIT_NUM; //开始计算 carry=0; x=a->msd; z=c->msd; res=x->num; while(1) { res+=carry*UNIT; z->num=res/b; carry=res%b; //开始计算当前精度 inc_prec+=DIGIT_NUM; if(inc_prec>precision) //已经达到需要的精度 { c->lsd=z; //确定指数 c->power=-inc_prec; break; } //必须这样标识,否则如果a和c一样,则下面会修改lsd if(x==a->lsd) x=NULL; if(x==NULL) { if(carry==0) //除得尽 { c->lsd=z; //确定指数 c->power=-inc_prec; break; } res=0; } else { x=x->lcell; res=x->num; } if(z==c->lsd) //增加节点 { if(ln_addcell(c,INIT_SIZE) ==NULL) { fprintf(stderr,"[%s %d] %s error,reason: ln_addcell fail\n",__FILE__,__LINE__,__FUNCTION__); return NULL; } c->lsd=c->msd->hcell; } z=z->lcell; } //获取精度 ln_fix(c,precision,mode); return c; }