POJ 1001 解题报告

    这道题主要是考察数的高精度乘法,使用数组存储数据,数组中的元素对于高精度数据中的某一位。我用的思想很简单,类似我们手算乘法时采用的步骤,这是在两层的for()循环中实现的。需要注意一个问题,如果采用unsigned char型存储元素,在运算的过程中Rslt[]元素的中间结果可能超过255,造成乘法结果的中间部分数据不正确。因此,Rslt[]进行累加时,需要及时进位。在我的程序中,对数据有效位前后有0的情况做了处理,避免乘法过程中出现过多不必要的运算。但这也导致刚开始对10.0000这样的数据处理出现错误,后来用dotPos的正负表示小数点的位置,解决了此问题。

   另外,对于高阶次幂,减少乘法使用的次数,采用降幂的思想。如2^9,可以看成(4^4)*2,进一步(16^2)*2。但是如何实现?这里,可以根据幂的二进制形式进行处理,如9表示成1001, 25表示成11001。具体见代码。注释部分采用这种思想,在VC运行通过。由于gcc没有对itoa实现,故submit的时候还用的传统方法。

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

unsigned char	Rslt[200] = {0};
int do_multiple(unsigned char *MultiA, unsigned char *MultiB, int lenA, int lenB)
{
	int		i, j, k;
	memset(Rslt, 0, sizeof(Rslt));
	for(i = 0; i < lenA; i++)
	{
		for(j = 0; j < lenB; j++)
		{
			Rslt[i+j] += MultiA[i]*MultiB[j];
			Rslt[i+j+1] += Rslt[i+j]/10;
			Rslt[i+j] %= 10;
		}
	}
	for(k = lenA+lenB-1; Rslt[k] == '\0'; k--){}
	return (k+1);
}
int main(void)
{
	int		Power, dotPos;
	int		num_len, rslt_len;
/*	char	Power_buf[5];	*/
	char	Num[10];
	unsigned char	ReverseNum[6];
	unsigned char	temp_rslt[200] = {0};

	int		i, j;
	while(scanf("%s %d", Num, &Power) == 2)
	{
/*		itoa(Power, Power_buf, 2);	*/
		dotPos = 0;
		for(i = 0; Num[i] != '\0'; i++)
		{
			if(Num[i] != '.')
				Num[i - (dotPos != 0)] = Num[i];
			else
				dotPos = i;
		}
		i -= (dotPos != 0);
		for(--i; (Num[i] == '0'); i--){}
		Num[i+1] = '\0';
		num_len = strlen(Num);
		dotPos = num_len - dotPos;
		for(j = 0; i >= 0; i--)
		{
			ReverseNum[j++] = Num[i]-'0';
		}
		memcpy(Rslt, ReverseNum, num_len);
		rslt_len = num_len;
		for(i = 1; i < Power; i++)
		{
			memcpy(temp_rslt, Rslt, rslt_len);
			rslt_len = do_multiple(temp_rslt, ReverseNum, rslt_len, num_len);
		}

/*		for(i = 1; i < (signed)strlen(Power_buf); i++)
		{
			memcpy(temp_rslt, Rslt, rslt_len);
			rslt_len = do_multiple(temp_rslt, temp_rslt, rslt_len, rslt_len);
			if(Power_buf[i] == '1')
			{
				memcpy(temp_rslt, Rslt, rslt_len);
				rslt_len = do_multiple(temp_rslt, ReverseNum, rslt_len, num_len);
			}
		}
*/
		dotPos *= Power;
		if(dotPos >= rslt_len)
		{
			putchar('.');
			for(i = dotPos; i > rslt_len; i--)
				putchar('0');
		}
		for(i = rslt_len; i > 0; i--)
		{
			if(dotPos == i)
				putchar('.');
			putchar(Rslt[i-1]+'0');
		}
		while(dotPos++ < 0)
			putchar('0');
		putchar('\n');
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值