首先将之前使用的内部函数一一说明实现
输入、输出:
/* 大整数扩大radix倍 大整数的每一位都要乘以radix */ int hbi_mul_radix(HBigInt *a, int radix){ <span style="white-space:pre"> </span>long i; <span style="white-space:pre"> </span>unsigned int carry=0,result; <span style="white-space:pre"> </span>if(0 == a->length){ <span style="white-space:pre"> </span>return RETURN_OK_BINT; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>for(i=0; i<a->length; i++){ <span style="white-space:pre"> </span>result = a->pBigInt[i] * radix + carry; <span style="white-space:pre"> </span>a->pBigInt[i] = (result & 0xffff) ; // it equals : result % CARRY_RADIX <span style="white-space:pre"> </span>carry = result >> BIT_PRE_WORD; // it equals : result / CARRY_RADIX <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if(carry){ <span style="white-space:pre"> </span>a->pBigInt[i] = carry; <span style="white-space:pre"> </span>a->length = i+1; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return RETURN_OK_BINT; } /* 大整数值增加data (一位十进制数) */ int hbi_add_int(HBigInt *a, int data){ <span style="white-space:pre"> </span>long i; <span style="white-space:pre"> </span>unsigned int carry=0,result; <span style="white-space:pre"> </span>a->pBigInt[0] += data; <span style="white-space:pre"> </span>if(0 == a->length){ <span style="white-space:pre"> </span>a->length = 1; <span style="white-space:pre"> </span>return RETURN_OK_BINT; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>for(i=0; i<a->length; i++){ <span style="white-space:pre"> </span>result = a->pBigInt[i] + carry; <span style="white-space:pre"> </span>a->pBigInt[i] = (result & 0xffff); <span style="white-space:pre"> </span>carry = result >> BIT_PRE_WORD; <span style="white-space:pre"> </span>if(0 == carry) break; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if(carry){ <span style="white-space:pre"> </span>a->pBigInt[i] = carry; <span style="white-space:pre"> </span>a->length = i+1; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return RETURN_OK_BINT; }
/* 大整数的输入,是指将字符串数组的转换成大整数表示, 从高位向低位输入,其中数组元素是0、1、2、3、4、5、6、7、8、9. 即可以将数组里面数看出十进制数的一位。第一个参数是大整数的指针,第二个是存储十进制的数组 */ int readHBInt(HBigInt *a,const char *str){ int y,res=0,neg; if(*str=='-'){ ++str; neg=-1; } else neg=1; setZeroHBInt(a); // 对a清0 y=*str-48; // asc码转换,由字符变成数字 a->pBigInt[0]=y; a->length=1; str++; //循环读入十进制的各位 while(*str!='\0') { y=*str-48; if(y < RADIX) { // 对大整数各位数乘以radix if((res=hbi_mul_radix(a,RADIX))!=RETURN_OK_BINT) { return res; } // 向大整数加上一位 if((res=hbi_add_int(a,y))!=RETURN_OK_BINT) { return res; } } else break; ++str; } a->sign=neg; trimHBInt(a); return RETURN_OK_BINT; } /* 大整数的输出,表示将B进制的大整数表示成十进制的字符数组输出。 数组每位元素是十进制的一位,从高位在前低位在后输出。 */ int writeHBInt(HBigInt *a, char *str) { unsigned int result1=0,result2=0; char *p=str; long i,j,len,tmp; un_short mark=0; HBigInt *dst=(HBigInt *)malloc(sizeof(HBigInt)); initHBInt(dst,INITIAL_BINT); extendHBInt(dst,a->length); assignHBInt(dst,a); len = a->length; i = len-1; if(0 == len) *p++='0'; while(len) { len=dst->length; if(dst->pBigInt[i] < RADIX) { mark=dst->pBigInt[i]; dst->pBigInt[i]=0; --i; len--; dst->length=len; if(0 == dst->length) { *p++=(char)(mark+48); goto LAST; } } //对大整数进行%10得出十进制的一位 for(j=len-1;j>=0;j--) { tmp = mark*CARRY_RADIX+dst->pBigInt[j]+result1*CARRY_RADIX; result2 = tmp / RADIX; result1 = tmp % RADIX; dst->pBigInt[j] = result2; mark=0; } *p++=(char)(result1+48); result1=0; trimHBInt(dst); } LAST: if(dst->sign==-1) *p++='-'; //添加大整数的符号 *p='\0'; reverStr(str); //反转数组元素,使十进制高位在前 deleteHBInt(dst); return RETURN_OK_BINT; }移位
/* 左移一个bit位 即: 扩大2倍 */ int Left_shift_bit(HBigInt *dst, HBigInt *src) { long len = 0; long i = 0; unsigned int carry = 0; int result = 0; un_short *pDst = dst->pBigInt; un_short *pSrc = src->pBigInt; // 确保目的大整数能够容纳移位后的结果 if(dst->alloclen < src->length+1 ) { // 扩大大整数空间,保证能够存储 if((result = extendHBInt(dst,src->length+1) != RETURN_OK_BINT)) { return result; } pDst = dst->pBigInt; } // 记录目的操作数原来的已用空间,方便后面处理 len = dst->length; dst->length = src->length; //pSrc = src->pBigInt; // 大整数数组元素分别左移一位,并赋给目的大整数 for(i = 0; i < src->length; ++i) { pDst[i] = (un_short)(carry = ((pSrc[i]) << 1) | (carry >> BIT_PRE_WORD)); } // 若最高数位左移后溢出,则将溢出的比特存到下一个字 if((carry >> BIT_PRE_WORD) != 0) { pDst[src->length] = (un_short)(carry >>BIT_PRE_WORD); ++(dst->length); } for(i=dst->length; i<len; ++i) pDst[i] = 0; // 清除可能残留的旧数据 dst->sign = src->sign; // 更改符号 return RETURN_OK_BINT; } /* 右移一个bit位 即: 缩小2倍 */ int Right_shift_bit(HBigInt *dst,HBigInt *src) { long oldlen = 0; //保存目的大整数的原来长度 long i = 0; unsigned int carry = 0; int result = 0; un_short temp = 0; un_short *pDst = dst->pBigInt; un_short *pSrc = src->pBigInt; // 确保目的大整数能够容纳移位后的结果 if(dst->alloclen < src->length) { // 扩展目的大整数长度 if((result = extendHBInt(dst,src->length) != RETURN_OK_BINT)) return result; pDst = dst->pBigInt; } oldlen = dst->length; dst->length = src->length; pSrc = src->pBigInt; for(i=src->length-1; i >= 0; --i) { /* 分别右移一位*/ temp = (un_short)((pSrc[i] >> 1) | (un_short)(carry << (BIT_PRE_WORD-1))); carry = (un_short)(pSrc[i] & (un_short)1); pDst[i] = temp; } for(i=dst->length; i<oldlen; ++i) pDst[i] = 0; // 清除可能残留的旧数据 dst->sign = src->sign; oldlen=dst->alloclen; pDst=dst->pBigInt+dst->alloclen-1; while(0 == *pDst--) oldlen--; //重新计算出目的大整数的长度 dst->length=oldlen; return RETURN_OK_BINT; }赋值:
/* 给大整数赋值 */ // 前提:dst被合理的initHBInt(即size要与src相同) void assignHBInt(HBigInt *dst,HBigInt *src) { dst->length = src->length; dst->sign = src->sign; memcpy(dst->pBigInt,src->pBigInt,sizeof(int)*src->alloclen); }互换:
//交换两个大整数 void swapHBInt(HBigInt *biA,HBigInt *biB) { un_short *tmp=NULL; biA->alloclen ^= biB->alloclen; biB->alloclen ^= biA->alloclen; biA->alloclen ^= biB->alloclen; biA->length ^= biB->length; biB->length ^= biA->length; biA->length ^= biB->length; biA->sign ^= biB->sign; biB->sign ^= biA->sign; biA->sign ^= biB->sign; tmp = biA->pBigInt ; biA->pBigInt = biB->pBigInt; biB->pBigInt = tmp; }最后是头文件定义:
typedef unsigned int un_short; /*16位数的声明符号*/ typedef unsigned long un_long; /*32位数的声明符号*/ #define RADIX 10 /* 进制数 */ #define CARRY_RADIX 65536 /* 每个pBigInt位所能表示的最大值 */ #define SIGNED_ZERO_BINT 0 /* 初始化大整数时的符号位 */ #define BIT_PRE_WORD 16 /* 每个单精度数字含有的bit数 */ #define RETURN_OK_BINT 0 /* 正常返回 */ #define RETURN_FAILE_BINT 1 <span style="white-space:pre"> </span>/* 错误返回 */ #define FAILE_MEMORY_BINT <span style="white-space:pre"> </span>2 /* 分配堆空间失败返回值 */ #define INITIAL_BINT <span style="white-space:pre"> </span>49 /* 默认分配的大小 */ #define STEP_BINT <span style="white-space:pre"> </span>16 /* 起跳值 */ /* 定义大整数的结构 */ typedef struct { long alloclen; /* 记录数组已经分配总的空间大小 */ long length; /* 记录大整数的长度,即实际使用空间大小 */ int sign; /* 记录大整数的符号 */ un_short *pBigInt; /* 记录大整数的实际数据位上的数值 */ } HBigInt;
后期工作:
1、改进算法,使能够并行化
2、完善已有功能(主要是从现有的实现上加以求精),扩展未有功能
比如:自平方算法的实现(使普通的n^2效率降低到(n+n^2/2)级别)、求常用的对数(log2、ln、lg等)
同时欢迎各位客官的批评指正!
原文地址:http://blog.csdn.net/yjbqzsf/article/details/41487249