| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4073 人关注过本帖
标题:[原创]高精度运算函数库(大整数运算)[位运算和指针的运用]
只看楼主 加入收藏
乌鸦丘比特
Rank: 1
等 级:新手上路
威 望:2
帖 子:625
专家分:0
注 册:2004-7-19
收藏
得分:0 
空前是用十进制的阿,不错的程序

我喜欢创造,一只扑腾着翅膀向天空飞翔的乌鸦
2005-04-11 17:14
时空之蕊
Rank: 2
等 级:新手上路
威 望:3
帖 子:691
专家分:0
注 册:2004-10-31
收藏
得分:0 
我也来热闹一下,一个礼拜后我也发表我的罗!

我渴望掌控时空的核心——用最先进的技术,打造无比美丽的世界!
2005-04-12 01:50
caili123456
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2005-12-22
收藏
得分:0 
2005-12-22 15:29
jhzh01
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2011-6-10
收藏
得分:0 
程序代码:
/*高精度函数库,利用补码储存,学习了一般整型算术运算的一些算法*/
/*为了提高效率,运用了比较多的位运算,可能影响可读性,我尽量加了注释*/
/*相关位运算语句: 左移<< ,右移>>,按位或|,按位且&,非~*/
/*函数依赖关系:算术辅助函数和赋值及输入输出函数的前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
快速回复:[原创]高精度运算函数库(大整数运算)[位运算和指针的运用]
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.035514 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved