空前是用十进制的阿,不错的程序
我喜欢创造,一只扑腾着翅膀向天空飞翔的乌鸦
/*高精度函数库,利用补码储存,学习了一般整型算术运算的一些算法*/ /*为了提高效率,运用了比较多的位运算,可能影响可读性,我尽量加了注释*/ /*相关位运算语句: 左移<< ,右移>>,按位或|,按位且&,非~*/ /*函数依赖关系:算术辅助函数和赋值及输入输出函数的前5个是基础函数,其它函数依赖于这些函数*/ /*写这个的目的是大家学习交流,也欢迎批评指正和提出建议。作者:乌鸦丘比特,crow262626@版权没有,盗版不究*/ /*一些常用的位运算:X&二进制数1111:N个1就是提取前N位,或者说求X除以2^N的余数;X>>(Y-1)&1: 提取第Y位;X>>Y:X/(2^Y)*/ #include<stdio.h> /**************数据及一些相关常量定义****************/ #define MAXSIZE 10 #define WITH 255 /*MAXSIZE: 高精度的最大值决定量,一个高精度数占MAXISIZE个字节*/ /*WITH: 二进制为连续8个1,用来取某个数的前8位和从char中取出前8位给int并防止负数高位补1*/ typedef struct hinum { char num[MAXSIZE]; } hinum ; /**************函数说明*****************/ /*赋值及输入输出函数*/ void hifirst(hinum*a); /*初始化a为0*/ hinum*hinew(int v); /*新建一个高精度空间并初十化为0,v=0则不初始化*/ void hidel(hinum*p); /*删除一个高精度空间*/ void higive0(hinum*dest,long number); /*整数->高精度*/ void higive1(hinum*dest,hinum*a); /*高精度->高精度*/ int higive2(hinum*dest,char*str); /*字符串->高精度,错误返回0*/ void higive3(char*str,hinum*a); /*高精度->字符串*/ int higets(hinum*dest); /*从键盘输入dest,错误返回0*/ void hiprint(hinum*dest); /*打印dest*/ /*算术运算辅助函数*/ void hileft(hinum*a,int step); /*a=a<<step*/ int hileft1(hinum*a); /*a=a<<1,返回原数最高位*/ int hiright1(hinum*a); /*a=a>>1,返回原数最低位*/ void hichg(hinum*a); /*a=-a*/ int hichk(hinum*a); /*if(a>=0)return 0;else return 1;*/ int hicount(hinum*a); /*返回a值为1的最高位*/ /*算术及比较运算函数*/ int hicmp(hinum*a,hinum*b); /*a>b返回1,a=b返回0,a<b返回-1*/ void hiadd1(hinum*a); /* a++ */ void hiadd0(hinum*a,long b); /*a=a+b*/ void hiadd(hinum*a,hinum*b); /*a=a+b*/ void hicut(hinum*a,hinum*b); /*a=a-b*/ void himuti(hinum*a,hinum*b); /* a=a*b */ int hidiv(hinum*a,hinum*b,hinum*mod); /*mod=a%b(a mod b),a=a/b*/ hinum*hioprate(hinum*a,hinum*b,char c,int v); /*运算函数,c为运算符号:'+','-','*','/';对于'+','-','*':v=0结果存在a中,否则新见建一个结果空间,对于'/',a=a/b,返回余数*/ /****测试函数****/ void hishow(hinum*a); /*显示a的二进制*/ /*****************************具体函数************************************/ /********赋值及输入输出函数********/ /*hifirst: 初始化a为0*/ void hifirst(hinum*a) { char*p ; int i ; p=a->num ; for(i=0;i<MAXSIZE;i++)p[i]=0 ; } /*hinew: 新建一个高精度空间并初十化为0,v=0则不初始化*/ hinum*hinew(int v) { hinum*p ; p=(hinum*)malloc(MAXSIZE); if(v)hifirst(p); return p ; } /*hidel: 删除一个高精度空间*/ void hidel(hinum*p) { free(p); } /*higive0: 整数->高精度*/ void higive0(hinum*dest,long number) { int i,v=0 ; if(number<0)v=1 ; for(i=0;i<4;i++) { (dest->num)[i]=number&WITH ; /*把long分为4个8位,分别取出放在a[0],a[1],a[2],a[3]*/ number=number>>8 ; } if(v) { /*按照数的正负剩下的每位补0或1*/ for(i=4;i<MAXSIZE;i++)(dest->num)[i]=~0 ; } else for(i=4;i<MAXSIZE;i++) (dest->num)[i]=0 ; } /*higive1: 高精度->高精度*/ void higive1(hinum*dest,hinum*a) { int i ; char*p1,*p2 ; p1=dest->num ; p2=a->num ; for(i=0;i<MAXSIZE;i++) p1[i]=p2[i]; } /*higive2: 字符串->高精度,错误返回0*/ int higive2(hinum*dest,char*str) { int v ; hinum tmp,*tmpp ; tmpp=&tmp ; if(str[0]=='-') { v=1 ; str++; } else v=0 ; hifirst(dest); while((*str)!='\0') { hileft1(dest); higive1(tmpp,dest); hileft(tmpp,2); hiadd(dest,tmpp); /*dest=dest*10:dest=(dest<<3)+(dest<<1)*/ if((*str)<'0'||(*str)>'9')return 0 ; /*出现非数字字符*/ hiadd0(dest,((*str)-'0')); str++; } if(v)hichg(dest); /*如果dest应该为负*/ return 1 ; } /*higive3: 高精度->字符串*/ void higive3(char*str,hinum*a) { char tmp[MAXSIZE*3],*number ; int i ; hinum temp,*tempp,ten,*tenp,mod,*modp,zero,*zerop ; tempp=&temp ; tenp=&ten ; modp=&mod ; zerop=&zero ; /*取地址*/ higive1(tempp,a); /*temp=a*/ higive0(tenp,10); /*ten=10*/ hifirst(zerop); /*zero=0*/ /*如果a为负*/ if(hichk(a)) { hichg(tempp); (*str)='-' ; str++; } number=modp->num ; i=0 ; if(!hicmp(tempp,zerop))tmp[i++]='0' ; /*除10取余,直到temp=0*/ while(hicmp(tempp,zerop)) { hidiv(tempp,tenp,modp); tmp[i++]=(*number)+'0' ; } while(i--) { *str=tmp[i]; str++; } *str='\0' ; } /*higets :从键盘输入dest,错误返回0*/ int higets(hinum*dest) { char tmp[MAXSIZE*3]; if(scanf("%s",tmp)!=1)return 0 ; /*输入错误*/ if(higive2(dest,tmp))return 1 ; /*把字符串转换为高精度*/ return 0 ; /*输入非数字字符串*/ } /*hiprint: 打印dest*/ void hiprint(hinum*dest) { char tmp[MAXSIZE*3]; higive3(tmp,dest); /*把高精度转换为字符串*/ printf("%s",tmp); } /********算术运算辅助函数********/ /*hileft: a=a<<step*/ void hileft(hinum*a,int step) { int i,stp1,stp2,stp3 ; char*p,tmp1,tmp2,with1 ; p=a->num ; stp1=step>>3 ; /*stp1=step/8,整体数组移动的步长*/ stp2=step&7 ; /*stp2=step%8;每个元素移动的步长*/ stp3=8-stp2 ; with1=(1<<stp2)-1 ; if(stp1) { i=MAXSIZE ; /*按照需要把整体数组先移动*/ while(i>stp1) { i--; p[i]=p[i-stp1]; } } /*补0*/ for(i=0;i<stp1;i++)p[i]=0 ; tmp2=0 ; /*i>=stp1每个元素左移*/ while(i<MAXSIZE) { tmp1=p[i]<<stp2 ; tmp1=tmp1|tmp2 ; tmp2=(p[i]>>stp3)&with1 ; /*取出将移到下一个元素的部分*/ p[i]=tmp1 ; i++; } } /*hileft1: a=a<<1,返回原数最高位*/ int hileft1(hinum*a) { int i ; char*p,tmp1,tmp2 ; p=a->num ; tmp2=0 ; for(i=0;i<MAXSIZE;i++) { tmp1=p[i]<<1 ; tmp1=tmp1|tmp2 ; /*补上p[i-1]的最高位*/ tmp2=(p[i]>>7)&1 ; /*取出p[i]的第8位*/ p[i]=tmp1 ; } return tmp2 ; } /*hiright1: a=a>>1,返回原数最低位*/ int hiright1(hinum*a) { int i,re ; char*p,tmp1,tmp2 ; tmp2=hichk(a); p=a->num ; for(i=MAXSIZE-1;i>=0;i--) { tmp1=(p[i]>>1)&127 ; /*右移后取7位*/ tmp1=tmp1|(tmp2<<7); /*最高位补上p[i+1]的最低位*/ tmp2=p[i]&1 ; /*取出最低位*/ p[i]=tmp1 ; } return tmp2 ; } /*hichg: a=-a*/ void hichg(hinum*a) { int i ; char*p ; p=a->num ; /*数组的每个元素取非*/ for(i=0;i<MAXSIZE;i++)p[i]=~p[i]; hiadd1(a); /*自加1得到相反数的补码*/ } /*hichk: if(a>=0)return 0;else return 1;*/ int hichk(hinum*a) { int ans ; ans=(a->num)[MAXSIZE-1]; ans=(ans>>7)&1 ; /*取出最左边一位:符号位*/ return ans ; } /*hicount: 返回a值为1的最高位*/ int hicount(hinum*a) { int i,j ; char*p ; p=a->num ; i=MAXSIZE ; /*从最高位向最低位扫描,遇1返回*/ while(i--) { j=8 ; while(j--) { if((p[i]>>j)&1)return((i<<3)|j); /*return (i*8+j);*/ } } } /********算术及比较运算函数********/ /*hicmp:a>b返回1,a=b返回0,a<b返回-1*/ int hicmp(hinum*a,hinum*b) { int i,j ; char*p1,*p2 ; if(hichk(a)) { if(hichk(b)) { p1=b->num ; p2=a->num ; } /*a,b都为负*/ else return-1 ; /*a为负b为正*/ } else { if(hichk(b))return 1 ; /*a为正b为负*/ p1=a->num ; p2=b->num ; /*a,b都为正*/ } i=MAXSIZE ; /*从最高位向最低位扫描*/ while(i--) { j=8 ; while(j--) { if((p1[i]>>j)&1) { if((p2[i]>>j)&1)continue ; return 1 ; /*p1>p2*/ } else { if((p2[i]>>j)&1)return-1 ; } /*p1<p2*/ } } /*while i*/ return 0 ; } /*hiadd1: a++*/ void hiadd1(hinum*a) { int i,tmp,next ; char*p ; p=a->num ; next=1 ; for(i=0;i<MAXSIZE;i++) { if(!next)break ; tmp=p[i]&WITH ; /*取出p[i]*/ tmp++; p[i]=tmp&WITH ; /*把自加的前8位赋给p[i]*/ next=tmp>>8 ; /*检查进位*/ } } /*hiadd0: a=a+b*/ void hiadd0(hinum*a,long b) { int i,tmp1,tmp2,next ; char*p1 ; p1=a->num ; next=0 ; for(i=0;i<4;i++) { tmp1=p1[i]&WITH ; /*取出p1[i]*/ tmp2=b>>(i*8)&WITH ; tmp1=tmp1+tmp2 ; if(next)tmp1++; /*如果上一次有进位*/ p1[i]=tmp1&WITH ; /*把结果的前8位赋给p[i]*/ next=tmp1>>8 ; /*检查进位*/ } while(next) { tmp1=p1[i]&WITH ; tmp1++; p1[i]=tmp1&WITH ; /*把结果的前8位赋给p[i]*/ next=tmp1>>8 ; /*检查进位*/ } } /*hiadd: a=a+b*/ void hiadd(hinum*a,hinum*b) { int i,tmp1,tmp2,next ; char*p1,*p2 ; p1=a->num ; p2=b->num ; next=0 ; for(i=0;i<MAXSIZE;i++) { tmp1=p1[i]&WITH ; /*取出p1[i]*/ tmp2=p2[i]&WITH ; tmp1=tmp1+tmp2 ; if(next)tmp1++; /*如果上一次有进位*/ p1[i]=tmp1&WITH ; /*把结果的前8位赋给p[i]*/ next=tmp1>>8 ; /*检查进位*/ } } /*hicut:a=a-b*/ void hicut(hinum*a,hinum*b) { hinum tmp,*tmpp ; /*a-b=a的补码+[-b]的补码*/ tmpp=&tmp ; higive1(tmpp,b); hichg(tmpp); hiadd(a,tmpp); } /*himuti: a=a*b */ void himuti(hinum*a,hinum*b) { int i,v,j,max1 ; char*p ; hinum ans,*ansp,b1,*b1p ; ansp=&ans ; b1p=&b1 ; /*得到地址*/ hifirst(ansp); /*ans=0*/ higive1(b1p,b); /*b1=b*/ p=b1.num ; if(v=hichk(a))hichg(a); if(hichk(b1p)) { v=!v ; hichg(b1p); } /*检查符号位并记录结果的符号位,如果为负换为它的相反数*/ max1=hicount(b); /*max1=b的值为1的最高位*/ /*二进制乘法,类似于笔算竖式*/ for(i=0;i<=max1;i++) { if((p[i>>3]>>(i&7))&1)hiadd(ansp,a); /*取出高精度数b的第i位,判断是否为1,为1则ans=ans+a*/ hileft1(a); /*a左移一位*/ } if(v)hichg(ansp); /*结果为负*/ higive1(a,ansp); } /*hidiv: mod=a%b(a mod b),a=a/b*/ int hidiv(hinum*a,hinum*b,hinum*mod) { int i,v,max1,max2,flag ; char*p ; hinum ans,*ansp,b1,*b1p ; ansp=a ; b1p=&b1 ; /*得到地址*/ higive1(b1p,b); higive1(mod,a); hifirst(ansp); if(v=hichk(mod))hichg(mod); if(hichk(b)) { v=!v ; hichg(b1p); } /*检查符号位并记录结果的符号位,如果为负换为它的相反数*/ max1=hicount(mod); max2=hicount(b1p); /*取出位数*/ if(max1<max2) { return 0 ; } /*除数的位数比被除数大*/ max1=max1-max2 ; hileft(b1p,max1); /*数据对齐*/ flag=0 ; /*加减交替法*/ for(i=0;i<max1;i++) { if(flag)hiadd(mod,b1p); /*flag=1:mod=mod-b1*/ else hicut(mod,b1p); /*flah=0:mod=mod+b1*/ flag=hichk(mod); /*mod>=0:flag=0;else:flag=1*/ hileft1(ansp); /*ans=ans<<1*/ if(!flag)hiadd1(ansp); /*flag=0:ans=ans+1*/ hiright1(b1p); /*b1=b1>>1*/ } if(flag)hiadd(mod,b1p); else hicut(mod,b1p); flag=hichk(mod); hileft1(ansp); if(!flag)hiadd1(ansp); /*和循环体比少了hiright1*/ /*求余数*/ while(hichk(mod))hiadd(mod,b1p); if(v)hichg(ansp); /*结果为负*/ return 0 ; } /*oprate:运算函数,c为运算符号;对于'+','-','*':v=0结果存在a中,否则新见建一个结果空间,对于'/',a=a/b,返回余数*/ hinum*hioprate(hinum*a,hinum*b,char c,int v) { hinum*p ; /*除法*/ if(c=='/') { p=hinew(1); hidiv(a,b,p); return p ; } if(v) { p=hinew(0); higive1(p,a); } /*需要新建结果空间*/ else p=a ; if(c=='+')hiadd(p,b); if(c=='-')hicut(p,b); if(c=='*')himuti(p,b); return p ; } /****测试函数****/ /*hishow: 显示a的二进制*/ void hishow(hinum*a) { int x,i,j ; char*p ; p=a->num ; for(i=MAXSIZE;i;i--) { for(j=8;j;j--) { x=(p[i-1]>>(j-1))&1 ; printf("%d",x); } printf(","); } printf("\n"); } /*****************************************************/