空前是用十进制的阿,不错的程序

我喜欢创造,一只扑腾着翅膀向天空飞翔的乌鸦
2005-04-11 17:14
2005-04-12 01:50
2005-12-22 15:29
程序代码:/*高精度函数库,利用补码储存,学习了一般整型算术运算的一些算法*/
/*为了提高效率,运用了比较多的位运算,可能影响可读性,我尽量加了注释*/
/*相关位运算语句: 左移<< ,右移>>,按位或|,按位且&,非~*/
/*函数依赖关系:算术辅助函数和赋值及输入输出函数的前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");
}
/*****************************************************/
2012-07-02 11:39