两个数相乘,小数点后的位数没有限制

前几天在网上看到这样一个题目 “两个数相乘,小数点后的位数没有限制,写一个高效算法“,在网上搜集到一些想法,感觉”先做大数乘法,然后再给结果加小数点“这种方法更好一些,用c语言实现了,分享给大家。如果大家有更好的方法,欢迎一起交流。

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

void longmulti(const char *a, const char *b, char *c);
void decimalmulti(char *a, char *b, char *c);

int main(void)
{
	char c[1024];
	decimalmulti("3.1415926", "3.14", c);
	printf("3.1415926 * 3.14 = %s\n\n", c);
	return 0;
}

void longmulti(const char *a, const char *b, char *c)
{
	int i, j, k, n, carry;
	int len_a, len_b;

	i = j = k = 0;
	//如果a,b中有一个是0,则整个运算的结果为0
	if(!strcmp(a, "0") || !strcmp(b, "0"))
	{
		c[0] = '0';
		c[1] = '\0';
		return;
	}
	//判断运算结果的正负号
	if(a[0] == '-')
	{
		i = 1;
		k = !k;
	}
	if(b[0] == '-')
	{
		j = 1;
		k = !k;
	}
	//如果出现了符号,先将符号过滤掉
	if(i || j)
	{
		if(k)
			c[0] = '-';
		longmulti(a+i, b+j, c+k);
		return;
	}
	len_a = strlen(a);
	len_b = strlen(b);

	memset(c, '0', len_a + len_b);
	c[len_a + len_b] = '\0';
	//各位数的运算
	#define I(a) (a - '0')
	for(i = len_a - 1; i >= 0; i--)
	{
		for(j = len_b - 1, k = i+j+1, carry = 0; j >= 0; j--, k--)
		{
			n = I(a[i]) * I(b[j]) + I(c[k]) + carry;
			c[k] = (n % 10) + '0';
			carry = n / 10;
		}
		c[k] += carry;
	}
	#undef I
	if(c[0] == '0')
		memmove(c, c+1, len_a + len_b);
}

void decimalmulti(char *a, char *b, char *c)
{
	/*
	len_a记录字符串a的长度
	len_b记录字符串b的长度
	len_c记录字符串c的长度
	dot_a记录小数点在字符串a中的位置,从1开始计数,即数组下标加1。
	dot_b记录小数点在字符串b中的位置。
	index记录相乘后的结果中应该有几位小数
	*/
	int len_a, len_b, len_c, i, j, k, dot_a, dot_b, index;

	len_a = strlen(a);
	len_b = strlen(b);
	dot_a = len_a;//小数点的位置为字符串的长度,表示不存在小数点
	dot_b = len_b;

	//将字符串a中的小数点去掉,并记录小数点的位置
	for(i = 0, k = 0; i < len_a; i++)
	{
		if(a[i] == '.')
			dot_a = i + 1;//在数组中的索引+1,为了方便后面计算
		else
			a[k++] = a[i];
	}
	a[k] = '\0';
	//将字符串b中的小数点去掉,并记录小数点的位置
	for(i = 0, k = 0; i < len_b; i++)
	{
		if(b[i] == '.')
			dot_b = i + 1;
		else
			b[k++] = b[i];
	}
	b[k] = '\0';

	//计算相乘后的结果总共有多少位小数
	index = (len_a - dot_a) + (len_b - dot_b);
	//大整数乘法
	longmulti(a, b, c);
	len_c = strlen(c);
	//为计算后的结果添加小数点
	if(index > 0)
	{
		for(i = len_c; i >= len_c - index; i--)
			c[i + 1] = c[i];
		c[len_c - index] = '.';
	}

	//过滤左边的0
	len_c = strlen(c);
	for(i = 0, j = 0; i < len_c; i++)
	{
		if(c[i+1] == '.' || c[i] != '0')
			break;
		j++;
	}
	if(j)
		memmove(c, c+j, len_c - j + 1);
	//过滤右边的0
	len_c = strlen(c);
	for(i = len_c - 1; i >= 0; i--)
		if(c[i] == '0')
			c[i] = '\0';
		else if(c[i] == '.')
		{
			c[i] = '\0';
			break;
		}
		else
			break;
}


你可能感兴趣的:(c,语言,相乘)