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

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

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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<b时返回负,a=b时返回0 */
int mcmp(mlong a, mlong b)
{
	if (strlen(a) == strlen(b))
		return strcmp(a, b);
	else return (strlen(a) - strlen(b));
}

/* 将形如0001或-0001前的0去掉 */
mlong mtrim(mlong m)
{
	int i;
	if ((m[0] == '-' && m[1] != '0') || (m[0] != '-' && m[0] != '0') || 
	    (m[0] == '-' && strlen(m) == 2) || (m[0] != '-' && strlen(m) == 1)) return m;
	if (m[0] == '-') i = 1;
	else i = 0;
	for (; i < strlen(m) - 1; i++) {
		if (m[i] != '0') break;
	}
	if (m[0] == '-') strcpy(m+1, m+i);
	else strcpy(m, m+i);	
	return m;
}

/* 将整数逆序,当整数前有多余的0时自动去掉 */
void mreverse(mlong m)
{
	int i,j;
	char t;
	for (i = 0, j = strlen(m) - 1; i < j; i++, j--) {
		t = m[i];
		m[i] = m[j];
		m[j] = t;
	}
	m = mtrim(m);
}


减法运算:

/* 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;
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值