整数高精度运算的库(加法,减法,乘法,除法,取模)

这几天开始做些ACM的Online Judge题目,遇到了个数据范围有10^100的题目,原题 是求两个整数的最小公倍数,没用高精写好算法后发现需要的运算类型比较多,基本除了加法没用到其他的都要,于是乎决定写这么个库,也能方便以后刷刷水题,^_^。

这是前面的声明部分,MAX_SIZE_MLONG为大整数的最大长度,将char*定义为mlong型也方便以后的代码书写及可读性。 

#include 
#include 
#include 
#define MAX_SIZE_MLONG 101
typedef char* mlong;


下面是除了基本运算之外的功能函数:

/* 分配MAX_SIZE_MLONG长度的字符指针 */
mlong new_mlong(void)
{
	return (mlong)malloc(sizeof(char) * (MAX_SIZE_MLONG + 1));
}


/* 比较两数大小,a>b返回正,a


减法运算:

/* a-b
 * 依赖:mreverse()
 */

mlong msub(mlong a, mlong b)
{
	mlong stmp;
	mlong r;
	char c;
	int i, h;
	int la, lb;
	int sign = mcmp(a, b);
	if (sign < 0) {
		stmp = a;
		a = b;
		b = stmp;
	}
	
	h = 0;
	la = strlen(a);
	lb = strlen(b);
	r = (mlong)malloc(sizeof(char) * (la + 1));
	for (i = 0; i < la; i++) {
		if (i < lb){
			c = b[lb-1-i];
		}
		else{
			c = '0';
		}
		if (h == 1 && (a[la-1-i] - 1)< c)
			r[i] = a[la-1-i] - c + 9 + '0';	
		else if (h == 1) {
			r[i] = a[la-1-i] - c - 1 + '0';	
			h = 0;
		}
		else if (a[la-1-i] < c) {
			r[i] = a[la-1-i] - c + 10 + '0';
			h = 1;	
		}
		else {
			r[i] = a[la-1-i] - c + '0';
		}
		
	}
	if (sign < 0) {
		r[i++] = '-';
		b = a;
		a = stmp;
	}
	r[i] = '\0';
	mreverse(r);		
	return r;
}


加法运算:

/* a+b 
 * 可以实现负数加法
 * 依赖:new_mlong(), mreverse(), msub(), msub()
 */
mlong madd(mlong a, mlong b)
{
	int i, h;
	int la, lb, l;
	int ia, ib;
	mlong r = new_mlong();
	if (a[0] == '-' && b[0] != '-') return msub(b, a+1);
	else if (a[0] != '-' && b[0] == '-') return msub(a, b+1);	
	else if (a[0] == '-' && b[0] == '-') {
		r[0] = '-';
		strcpy(r+1, madd(a+1, b+1));
	}
	else{
		la = strlen(a);
		lb = strlen(b);
		l = (la > lb) ? la : lb;
		h = 0;
		for (i = 0; i < l; i++) {
			ia = ((la-1-i) < 0) ? 0 : a[la-1-i] - '0';
			ib = ((lb-1-i) < 0) ? 0 : b[lb-1-i] - '0';
			r[i] = (ia + ib + h) % 10 +  +'0';
			h = (ia + ib + h) / 10;
		}
		if(h) r[i++] = '1';
		r[i] = '\0';
		mreverse(r);
	}
	return r;
}

乘法运算:

/* a*b
 * 依赖:MAX_SIZE_MLONG, mreverse()
 */
mlong mmul(mlong a, mlong b){
	int i, j;
	int h;
	int m;
	mlong r = (mlong)malloc(sizeof(char)*(MAX_SIZE_MLONG * 2 + 1));
	memset(r, '0', MAX_SIZE_MLONG * 2 + 1);
	int la = strlen(a);
	int lb = strlen(b);
	for (j = 0;j < lb; j++) {
		h = 0;
		if (b[lb-j-1] == '0') continue;
		for (i = 0; i < la; i++) {
			m = (b[lb-j-1]-'0') * (a[la-i-1]-'0') + r[i+j]-'0' + h;
			r[i+j] = m % 10 + '0'; 
			h = m / 10;
		}	
		if (h){
			r[la+j] = '0' + h;
			if (j == lb-1) r[la+j+1] = '\0';
		}
		else if (j == lb-1) r[la+j] = '\0';
	}
	mreverse(r);
	return r;
}

除法运算:

/* a/b
 * 依赖:mtrim(), mcmp(), mmul(), msub()
 */
mlong mdiv(mlong a, mlong b)
{
	int la, l;
	int i, j;
	mlong res, rem, h, mi, mii;
	la = strlen(a);
	res = (mlong)malloc(sizeof(char) * (la+1));
	
	if (mcmp(a, b) < 0) {
		res = realloc(res, sizeof(char)*2);
		strcpy(res, "0");
		return res;
	}
	rem = (mlong)malloc(sizeof(char) * 2);
	h = (mlong)malloc(sizeof(char) * (la+1));
	mi = (mlong)malloc(sizeof(char) * 2);
	mii = (mlong)malloc(sizeof(char) * 2);
	strcpy(mi, "0");
	strcpy(mii, "1");
	strcpy(rem, "0");
	for (i = 0; i < la; i++) {
		strcpy(h, rem);
		l = strlen(h);
		h[l] = a[i];
		h[l+1] = '\0';
		h = mtrim(h);
		for (j = 0; j <= 9; j++) {
			mi[0] = '0' + j;
			mii[0] = '0' + j + 1;
			if ((j == 9) || (mcmp(h, mmul(mii, b)) < 0)) {
				free(rem);
				rem = msub(h, mmul(mi, b));
				res[i] = j + '0'; 
				break;
			}
		}
	}
	res[i] = '\0';
	mtrim(res);
	return res;

}

取模运算:

/* a%b
 * 依赖:mtrim(), mcmp(), mmul(), msub()
 */
mlong mmod(mlong a, mlong b)
{
	int la, l;
	int i, j;
	mlong rem, h, mi, mii;
	la = strlen(a);
	if (mcmp(a, b) < 0) {
		return a;
	}
	rem = (mlong)malloc(sizeof(char) * 2);
	h = (mlong)malloc(sizeof(char) * (la+1));
	mi = (mlong)malloc(sizeof(char) * 2);
	mii = (mlong)malloc(sizeof(char) * 2);
	strcpy(mi, "0");
	strcpy(mii, "1");
	strcpy(rem, "0");
	for (i = 0; i < la; i++) {
		strcpy(h, rem);
		l = strlen(h);
		h[l] = a[i];
		h[l+1] = '\0';
		h = mtrim(h);
		for (j = 0; j <= 9; j++) {
			mi[0] = '0' + j;
			mii[0] = '0' + j + 1;
			if ((j == 9) || (mcmp(h, mmul(mii, b)) < 0)) {
				free(rem);
				rem = msub(h, mmul(mi, b));
				break;
			}
		}
	}
	return rem;
}

 使用以上函数时需注意的是不能用在负整数上,不过对于相减得到负数的情况结果会有负号。代码还有许多待改进的地方,有建议童鞋以及大神们欢迎提啊。

你可能感兴趣的:(整数高精度运算的库(加法,减法,乘法,除法,取模))