【思考题】任意长度有理数乘法运算

目标需求:

//描述:
//长数相乘
//请编程实现:两个任意长度的数相乘,请输出结果.
//详细要求以及系统约束
//1)两个数可能是小数、整数、正数、负数;
//2)输入输出均为字符串形式,输入的字符串以“\0”结束,输出的结果字符串也必须以“\0”结束;
//3)输入的字符串不能是空字符串或非法字符串,否则返回-1,其他情况返回0;
//4)输出的结果字符串需要过滤掉整数位前以及小数位后无效的0,小数位为全0的,直接输出整数位;
//例1:相乘结果为11.345,此数值前后均不可以带0,“011.345”或者“0011.34500”等等前后带无效0的均视为错误输出。
//例2:080 × 0.125 结果是“10”
//5)输出的结果如果是正数或0需要过滤掉前面的+号。
//例1:相乘结果为+121,则“+121”为错误输出,“121”为正确输出。
//输入:
//输入两个任意长度的数
//输出:
//输出相乘的结果,如果输入的数不规范,输出结果为空
//样例输入:
//100000
//500000
//样例输出:
//50000000000

思路:

首先实现字符串加法,去除乘数以及被乘数的小数点,计算结果小数点位置,被乘数逐位与乘数相乘并进行相对的左移位(乘10),然后对这些逐位相乘结果进行相加即可。

得到结果再进行截头截尾(去除结果字符串的开始的0串和小数末尾的0串)。

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

void str_z(char* s1, char* s2, char **s1z, char **s2z, int *sign){
	int s1sign=1,s2sign=1;

	if(s1[0]=='-'){
		s1sign=-1;
		*s1z = &s1[1];
	}
	else
		*s1z = s1;
	if(s2[0]=='-'){
		s2sign=-1;
		*s2z = &s2[1];
	}
	else
		*s2z = s2;
	*sign = s1sign*s2sign;
}

void zheng_xiao_fenli(char *s1, char* s2, int *xiaoshu_cnt, char **s1_num, char **s2_num){
	int s1len, s2len;
	int k1, k2, s1_xiaoshu_cnt=0, s2_xiaoshu_cnt=0;

	s1len = strlen(s1);
	s2len = strlen(s2);

	for(k1=s1len-1; k1>=0; k1--){
		if(s1[k1]>='0'&&s1[k1]<='9')
			continue;
		else if(s1[k1]=='.')
			s1_xiaoshu_cnt += s1len-k1-1;
		else{
			exit(0); //非法字符
		}
	}

	if(s1_xiaoshu_cnt==0){
		*s1_num = s1;
	}
	else{
		*s1_num = (char*)malloc(sizeof(char)*s1len);
		/*if(*s1_num==NULL){
			printf("malloc failed!\n");
			exit(0);
		}*/
		memcpy(*s1_num, s1, sizeof(char)*(s1len-s1_xiaoshu_cnt-1));
		memcpy(*s1_num+s1len-s1_xiaoshu_cnt-1, s1+s1len-s1_xiaoshu_cnt, sizeof(char)*s1_xiaoshu_cnt);
		*(*s1_num+s1len-1) = '\0';
	}

	for(k2=s2len-1; k2>=0; k2--){
		if(s2[k2]>='0'&&s2[k2]<='9')
			continue;
		else if(s2[k2]=='.')
			s2_xiaoshu_cnt += s2len-k2-1;
		else{
			exit(0); //非法字符
		}
	}

	if(s2_xiaoshu_cnt==0){
		*s2_num = s2;
	}
	else{
		*s2_num = (char*)malloc(sizeof(char)*s2len);
		/*if(*s2_num==NULL){
			printf("malloc failed!\n");
			exit(0);
		}*/
		memcpy(*s2_num, s2, sizeof(char)*(s2len-s2_xiaoshu_cnt-1));
		memcpy(*s2_num+s2len-s2_xiaoshu_cnt-1, s2+s2len-s2_xiaoshu_cnt, sizeof(char)*s2_xiaoshu_cnt);
		*(*s2_num+s2len-1) = '\0';
	}

	*xiaoshu_cnt = s1_xiaoshu_cnt+s2_xiaoshu_cnt;
}

char* str_add(char* s1, char* s2){
	int s1len,s2len,anslen;
	int k1,k2,ansk,c,s;
	char *ans,*ansrtn;

	s1len=strlen(s1);
	s2len=strlen(s2);

	anslen=s1len>s2len?s1len+1:s2len+1;
	ans = (char*)malloc(sizeof(char)*(anslen+1));
	/*if(ans==NULL){
		printf("malloc failed!\n");
		exit(0);
	}*/
	k1 = s1len-1;
	k2 = s2len-1;
	ansk = anslen-1;
	s=0; c=0;
	while(k1>=0||k2>=0){
		if(k1>=0&&k2>=0){
			c = s1[k1--]+s2[k2--]-'0'-'0'+s;
			ans[ansk--] = c%10+'0';
			s = c/10;
		}
		else if(k1>=0){
			c = s1[k1--]-'0'+s;
			ans[ansk--] = c%10+'0';
			s = c/10;
		}
		else if(k2>=0){
			c = s2[k2--]-'0'+s;
			ans[ansk--] = c%10+'0';
			s = c/10;
		}
	}
	ans[0] = s+'0';
	ans[anslen] = '\0';
	for(ansk=0; ansk<anslen; ansk++){
		if(ans[ansk]!='0')
			break;
	}
	if(ansk!=0){
		ansrtn = (char*)malloc(sizeof(char)*(anslen-ansk+1));
		if(ansrtn==NULL){
			printf("malloc failed!\n");
			exit(0);
		}
		strcpy(ansrtn, &ans[ansk]);
		free(ans);
		return ansrtn;
	}
	else
		return ans;
}

char* str_mul(char* s1, char* s2){
	int s1len, s2len, k1, k2, k;
	char* mul_temp, *temp, *del_temp;
	int mul_temp_len;
	char* add_temp;

	s1len = strlen(s1);
	s2len = strlen(s2);

	add_temp = (char*)malloc(sizeof(char)*2);
	/*if(add_temp==NULL){
		printf("malloc failed!\n");
		exit(0);
	}*/
	add_temp[0] = '0';  add_temp[1] = '\0';
	for(k1=0; k1<s1len; k1++){
		mul_temp = (char*)malloc(sizeof(char)*2);
		/*if(mul_temp==NULL){
			printf("malloc failed!\n");
			exit(0);
		}*/
		mul_temp[0] = '0';  mul_temp[1] = '\0';
		if(s1[k1]=='0')
			continue;
		for(k=s1[k1]-'0'; k>0; k--){
			del_temp = mul_temp;
			mul_temp = str_add(mul_temp, s2);
			free(del_temp);
		}
		mul_temp_len = strlen(mul_temp);
		temp = (char*)malloc(sizeof(char)*(mul_temp_len+s1len-k1));
		/*if(temp==NULL){
			printf("malloc failed!\n");
			exit(0);
		}*/
		memset(temp, '0', sizeof(char)*(mul_temp_len+s1len-k1));
		memcpy(temp, mul_temp, sizeof(char)*mul_temp_len);
		temp[mul_temp_len+s1len-k1-1] = '\0';
		free(mul_temp);
		mul_temp = temp;
		add_temp = str_add(mul_temp, add_temp);
	}

	//printf("%s", add_temp);
	return add_temp;
}

int main(void){
	char s1[100];
	char s2[100];
	int sign, xs_cnt, k, kk, kp;
	char *s1z, *s2z;
	char *s1zheng, *s1xiao, *s2zheng, *s2xiao, *s1_num, *s2_num;
	char *ans; int anslen, xs_cnt_temp;

	gets(s1);
	gets(s2);

	str_z(s1, s2, &s1z, &s2z, &sign);
	zheng_xiao_fenli(s1z, s2z, &xs_cnt, &s1_num, &s2_num);
	ans = str_mul(s1_num, s2_num);
	anslen = strlen(ans);

	printf("\n");
	if(sign==-1)
		printf("-");
	if(xs_cnt==0){
		printf("%s", ans);
	}
	else{
		if(anslen<=xs_cnt){
			for(k=anslen-1; k>=0; k--){
				if(ans[k]!='0')
					break;
			}
			printf("0.");
			xs_cnt_temp = xs_cnt-anslen;
			while(xs_cnt_temp--){
				printf("0");
			}
			for(kk=0; kk<=k; kk++){
				printf("%c", ans[kk]);
			}
		}
		else{
			for(k=0; k<anslen-xs_cnt; k++){
				printf("%c", ans[k]);
			}
			for(kk=anslen-1; kk>=k; kk--){
				if(ans[kk]!='0')
					break;
			}
			if(kk!=k-1){
				printf(".");
				for(kp=k; kp<=kk; kp++){
					printf("%c", ans[kp]);
				}
			}
		}
	}

	system("pause");
	return 0;
}

结果演示:



posted @ 2014-08-11 23:58  浴火重生-xhyz  阅读(167)  评论(0编辑  收藏  举报