巨大数四则运算

大数的四则运算

    历经10天时间完成了整数巨大数的四则运算,一方面由于太懒没有同时完成小数巨大数部分,另一方面小数巨大书的完成也是建立在整数的基础之上,这也是没有同时完成小数部分的一个主要原因。完成整数是一个摸索的过程,完成之后在技术上有一定的成熟,再转向小数效率会更加的高,整体大框架也会更好,不必大作改动。

    实现大数的目的在于,解决超出计算机可表示范围数据的存储以及运算,计算机中各类型数据可表示的范围见头文件limist.h,这里摘取部分代码,以int为例当超过-217483648~2147483647范围数字计算机就不能正常表示,需要设计一种数据结构来存储大数,大数在密码学中广泛运用,大数的运算往往涉及上百千位的运算。本篇文章将重点讲述大数的存储以及大数的四则运算。

#define MB_LEN_MAX    2             /* max. # bytes in multibyte char */
#define SHRT_MIN    (-32768)        /* minimum (signed) short value */
#define SHRT_MAX      32767         /* maximum (signed) short value */
#define USHRT_MAX     0xffff        /* maximum unsigned short value */
#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX       2147483647    /* maximum (signed) int value */
#define UINT_MAX      0xffffffff    /* maximum unsigned int value */
#define LONG_MIN    (-2147483647L - 1) /* minimum (signed) long value */
#define LONG_MAX      2147483647L   /* maximum (signed) long value */
#define ULONG_MAX     0xffffffffUL  /* maximum unsigned long value */

#if     _INTEGRAL_MAX_BITS >= 8
#define _I8_MIN     (-127i8 - 1)    /* minimum signed 8 bit value */
#define _I8_MAX       127i8         /* maximum signed 8 bit value */
#define _UI8_MAX      0xffui8       /* maximum unsigned 8 bit value */
#endif

#if     _INTEGRAL_MAX_BITS >= 16
#define _I16_MIN    (-32767i16 - 1) /* minimum signed 16 bit value */
#define _I16_MAX      32767i16      /* maximum signed 16 bit value */
#define _UI16_MAX     0xffffui16    /* maximum unsigned 16 bit value */
#endif

#if     _INTEGRAL_MAX_BITS >= 32
#define _I32_MIN    (-2147483647i32 - 1) /* minimum signed 32 bit value */
#define _I32_MAX      2147483647i32 /* maximum signed 32 bit value */
#define _UI32_MAX     0xffffffffui32 /* maximum unsigned 32 bit value */
#endif

1、大数的存储

    大数获取采取从txt文件中获得,将得到的数据按照万进制存储到int的数据,这里解释一下我们采取的为什么是万进制而不是更大的进制,因为不仅要完成巨大数的存储还要完成四则运算,在涉及乘法的部分,10000*10000小于整型的上限2147483647,不会产生溢出的情况,而更大的进制10万相乘则会溢出,同时从文件中读取的数据为十进制数字,而10000是10的次方,在转换进制的方面万进制提供了很好的便利,只需要每4位取出一个十进制数字存放到数组中即可,所以说10000是最合适的进制。

    那么根据上述分析可以得到大数的结构体如下,number_sign来表示大数的正负,0正1负,number_array表示巨大数的数据部分,number_count记录数组的长度。

typedef struct HUGENUMBER {
	char number_sign;			//标记正负符号
	int *number_array;		//指向存储巨大数的数组
	int number_count;			//数组中元素个数
}HUGENUMBER;

读取文件的时候我们先得到文件中数据的长度file_length,假设文件提供的数据都是合法字符,不存在字母的情况,这里需要注意的是文件中可能存放数据第一个字符可能是’-’或者’+’,巨大数的实际长度就需要相应变化,如果读到的第一个字符是0-9之间说明没有正负号字符,反之则存在正负号字符需要对上面得到的file_length减一。根据得到的文件长度就可以去申请存放巨大数数组空间,数组的长度number_count = (file_length + 3) / 4,存放的时候先存放巨大数最高位的数据,因为最高位的数字不一定是4个,例如234 5268 5982,先存放高位的234,存放最高位数字技巧如下:

在把巨大数从文件中存放到结构体数组的函数里,给出了一个只读数组,作用在与存放最大数的最高位数字,通过file_length % 4,当做数组下标取出字符串,当做fscanf函数的格式符便可取出最高位的数字。

const char *format[4] = {"%4d", "%1d","%2d", "%3d"};  

fscanf(fp,format[file_length % 4], &myNumber->number_array[myNumber->number_count- 1]);

剩下数字都可以每4位取得。存放的方式遵循将巨大数高位存放在数组高位,低位存放在低位,为后续的加减提供便利,存储的部分就完成。如下图

存储数据部分代码如下

//The read file operation in this section is only for integer operations,
// not counting the decimal, and needs to be modified.
void initHugeNumber(HUGENUMBER *myNumber, FILE *fp) {
	int file_length;
	int beginIndex;
	int i;
	char firstSign;
	const char *format[4] = {"%4d", "%1d", "%2d", "%3d"};		

	fseek(fp, 0, SEEK_END);    
	file_length = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	fread(&firstSign, sizeof(char), 1, fp);							
//先读一个字符判断是不是数字,决定巨大数实际起始位置
	beginIndex = ('0' <= firstSign && firstSign <= '9') ? 0 : 1;    
//文件中巨大数实际实际起始位置
	file_length += ('0' <= firstSign && firstSign <= '9') ? 0 : -1;
 //文件中巨大数实际长度 以此来计算申请数组长度
	fseek(fp, beginIndex, SEEK_SET);
	myNumber->number_sign = (firstSign == '-') ? NEGATIVE_SIGN : POSTIVE_SIGN;
	myNumber->number_count = (file_length + 3) / 4;
	myNumb
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值