加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

大数的加减法、乘除法 code

发布时间:2020-12-14 03:54:25 所属栏目:大数据 来源:网络整理
导读:大数:超过计算机默认可表示的最长值 这里的实现未考虑小数,大数可以含正负符号,可含前导零(如+000001111、-0000000) 大数用字符串表示 #include stdio.h#include stdlib.h#include string.hbool IsDigital(const char *string) { if (*string == '-' ||

大数:超过计算机默认可表示的最长值

这里的实现未考虑小数,大数可以含正负符号,可含前导零(如+000001111、-0000000)

大数用字符串表示


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool IsDigital(const char *string)  
{  
	if (*string == '-' || *string == '+')
		string++;
	
		while(*string >= '0' && *string <= '9')
		string++;
	
	return *string ? false : true;
}  

/**
 * brief 倒转字符串
 */
void StrAjust(char *string)  
{  
	int length = strlen(string);  
	int tmp;  
	for(int i = 0; i < length / 2; i++)  
	{  
		tmp = string[i];  
		string[i] = string[length - i - 1];  
		string[length - i - 1] = tmp;  
	}  
}
/**
 * brief 大数比较,通过值/结果参数ret返回比较结果
 */
int BignumCmp(const char *num1,const char *num2,int *ret)
{
	int len1,len2,len;
	const char *tmp1 = num1,*tmp2 = num2;
	
	if (!num1 || !num2)
		return -1;
	len1 = strlen(num1),len2 = strlen(num2);
	
	if (*num1 == '-' || *num1 == '+')
		tmp1++,len1--;
	
	if (*num2 == '-' || *num2 == '+')
		tmp2++,len2--;
	
	if (len1 > len2) {
		len1 = len1 - len2;
		len2 = 0;
	} 
	else {
		len2 = len2 - len1;
		len1 = 0;
	}
	
	*ret = 0;
	for (len = 0; len < len1; len++) {
		if (tmp1[len] != '0') {
			*ret = 1;
			break;
		}
	}
	
	for (len = 0; len < len2; len++) {
		if (tmp2[len] != '0') {
			*ret = -1;
			break;
		}
	}
	
	if (*ret == 0) {
		while (tmp1[len1] && tmp2[len2]) {
			if (tmp1[len1] != tmp2[len2]) {
				*ret = tmp1[len1] - tmp2[len2];
				break;
			}
			len1++,len2++;
		}
	}

	if (*num1 != '-') {
		if (*num2 == '-')
			*ret = *ret >= 0 ? *ret : 1;
	}
	else {
		if (*num2 == '-')
			*ret = 0 - *ret;
		else
			*ret = *ret <= 0 ? *ret : -1;
	}
	
	return 0;	
}

/**
 * brief 大数加/减法,可以带符号位'+'/'-',*/
char *BignumSum(const char *num1,const char *num2)
{
#define NUMM (3)
	int cmp,ret,flag,blen,slen,increment;
	const char *tmp1 = num1,*tmp2 = num2,*bigger,*smaller;
	char *res,*rp,sign;
	
	if (!num1 || !num2)
		return NULL;
	
	flag = 0;
	if ((*num1 == '-' && *num2 == '-') || (*num1 != '-' && *num2 != '-'))
		flag = 1;
		
	if (*num1 == '-' || *num1 == '+')
		tmp1 = num1 + 1;
	if (*num2 == '-' || *num2 == '+')
		tmp2 = num2 + 1;
		
	ret = BignumCmp(tmp1,tmp2,&cmp);
	if (ret)
		return NULL;
		
	if (!cmp && !flag) {
		res = (char *)malloc(NUMM);
		if (!res)
			return NULL;
		rp = res;
		*rp++ = '0';
		*rp = 0;
		return res;
	}
		
	if (cmp > 0){
		bigger = tmp1,sign = *num1;
		smaller = tmp2;
	} 
	else {
		bigger = tmp2,sign = *num2;
		smaller = tmp1;
	}
	blen = strlen(bigger);
	slen = strlen(smaller);
	
	// + NUMM: 包含结束符、符号位、可能的进位
	res = (char *)malloc(blen + NUMM);
	if (!res)
		return NULL;
	rp = res;
	if (sign == '-')
		*rp++ = '-';
	
	// 从个位开始往高位依次相加
	for (increment = 0; blen > 0;) {
		int tmp;
		char smallernum = slen > 0 ? smaller[--slen] - '0' : 0;
		if (flag) {
			tmp = bigger[--blen] - '0' + smallernum + increment;
			increment = tmp / 10;
		}
		else {
			tmp = bigger[--blen] - '0' - smallernum + increment;
			tmp = tmp < 0 ? (increment = -1,tmp + 10) : (increment = 0,tmp);
		}
		*rp++ = tmp % 10 + '0';
	}
	
	// 最高位进位
	if (increment)
		*rp++ = increment + '0';
	
	// 清除前缀零
	*rp = 0;
	while (*(--rp) == '0')
		*rp = 0;
	
	rp = res;
	if (sign == '-')
		rp = res + 1;
	StrAjust(rp);
	
	return res;
}

/**
 * brief 大数乘法,*/
char *BignumMulti(const char *num1,const char *num2)
{
	int increment,len1,len2;
	char *res,*rp;
	if (!num1 || !num2)
		return NULL;
	
	len1 = strlen(num1);
	len2 = strlen(num2);
	res = (char *)malloc(len1 + len2 + 1);
	if (!res)
		return NULL;
	memset(res,len1 + len2 + 1);
	rp = res;
	
	if ((*num1 == '-' && *num2 != '-') || (*num1 != '-' && *num2 == '-'))
		*rp++ = '-';
	
	if (*num1 == '-' || *num1 == '+') {
		num1++,len1--;
	}
	if (*num2 == '-' || *num2 == '+') {
		num2++,len2--;
	}
	
	// num1 乘数, num2 被乘数
	for (int i = len1 - 1; i >= 0; i--) {
		int j,num1tmp = num1[i] - '0';
		increment = 0;
		for (j = len2 - 1; j >= 0; j--) {
			int tmp1;
			char *tmp2; 
			tmp1 = num1tmp * (num2[j] - '0') + increment;
			tmp2 = rp + len1 - i + len2 - j - 2;
			tmp1 = *tmp2 + tmp1;
			*tmp2 = tmp1 % 10;
			increment = tmp1 / 10;
		}
		if (increment)
			*(rp + len1 - i + len2 - 1) = increment;	
	}
	rp = rp + len1 + len2 - 1;
	
	// 清除前导零
	while (*rp == 0)
		rp--;
	
	if (rp < res || (*res == '-' && rp == res)) {
		*res = '0';
		return res;
	}

	while (rp >= res && *rp != '-') {
		*rp = *rp + '0';
		rp--;
	}
	
	rp = res;
	if (*res == '-')
		rp = res + 1;
		
	StrAjust(rp);
	return res;
}

/**
 * brief 大数求相反数,*/
char *BignumMinus(const char*num)
{
	int len;
	char *res,*rp;
	const char *tmp;
	
	if (!num)
		return NULL;
	
	tmp = num;
	while (*tmp == '-' || *tmp == '+' || *tmp == '0')
		tmp++;
		
	len = strlen(tmp);
	
	res = (char *)malloc(len + 2);
	if (!res)
		return NULL;
	
	if (!len) {
		*res = '0';
		*(res + 1) = 0;
		return res;
	}
	
	rp = res;
	if (*num != '-') {
		*res = '-';
		rp++;
	}
		
	strcpy(rp,tmp);
	return res;
}

/**
 * brief 大数除法,*/
char *BignumDivi(const char *num1,const char *num2)
{
	int cmp,len;
	char *tmp,*res;
	char *tmp1,*tmp2;
	
	
	if (!num1 || !num2)
		return NULL;
	if (BignumCmp(num2,"0",&cmp) || !cmp)
		return NULL;
	
	for (tmp1 = (char *)num1; *tmp1 && (*tmp1 == '-' || *tmp1 == '+' || *tmp1 == '0'); tmp1++) ;
	for (tmp2 = (char *)num2; *tmp2 && (*tmp2 == '-' || *tmp2 == '+' || *tmp2 == '0'); tmp2++) ;
	
	len1 = strlen(tmp1),len2 = strlen(tmp2);

	res = (char *)malloc(2);
	if (!res)
		return NULL;
	memset(res,2);
	
	BignumCmp(tmp1,&cmp);
	if (cmp < 0) {
		*res = '0';
	}
	else if (cmp == 0) {
		*res = '1';
	}
	else {	
		tmp = (char *)malloc(len1 + 1);
		if (!tmp) {
			free(res);
			return NULL;
		}
		strncpy(tmp,len1 + 1);
		tmp2 = tmp;
		
		tmp = (char *)malloc(len1 + 1);
		if (!tmp) {
			free(res);
			free(tmp2);
			return NULL;
		}
		strncpy(tmp,tmp1,len1 + 1);
		tmp1 = tmp;
	
		len = len1 - len2;
		while (len >= 0) { // 被除数比除数多len个字符
			int start = 0,end = 9;
			char *rest,increment[2] = {0};
			
			memset(tmp2 + len2,'0',len);  // 补零
			tmp2[len2 + len] = 0;
			
			// 二分查找合适的除法结果
			while (start <= end) {
				int mid = (start + end) / 2;
				
				if (mid == start && start < end)
					mid++;
				increment[0] = mid + '0';
				
				rest = BignumMulti(tmp2,increment);
				
				if (start == end)
					break;
					
				BignumCmp(tmp1,rest,&cmp);
				if (cmp >= 0)
					start = mid;
				else
					end = mid - 1;
				free(rest);
			}
			
			tmp = BignumMinus(rest);
			free(rest),rest = tmp;
			tmp = BignumSum(tmp1,rest);
			free(tmp1),free(rest),tmp1 = tmp;
			
			increment[0] = start + '0';
			rest = BignumMulti(res,"10");
			free(res),res = rest;
			rest = BignumSum(res,increment);
			free(res),res = rest;
	
			len--;
		}
		free(tmp1);
		free(tmp2);
	}
	
	if ((*num1 == '-' && *num2 != '-') || (*num1 != '-' && *num2 == '-')) {
		tmp = BignumMinus(res);
		free(res),res = tmp;
	}
	
	return res;	
}


int main(int argc,char **argv)  
{ 
	bool ret1,ret2;
	char *multi,*sum,*divi;
	
	if(3 != argc)  
		return -1;   
	
	ret1 = IsDigital(argv[1]);  
	ret2 = IsDigital(argv[2]);  
	
	if(!ret1 || !ret2) {  
		printf("input errorn");  
		return -1;  
	}  
	sum= BignumSum(argv[1],argv[2]);  
	multi= BignumMulti(argv[1],argv[2]);
	divi = BignumDivi(argv[1],argv[2]);	

	printf("num1:%snnum2:%snsum:%snmulti:%sndivi: %sn",argv[1],argv[2],sum,multi,divi);
	
	free(sum);
	free(multi);
	free(divi);
	
	return 0;  
}  

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读