POJ1001 Exponentiation 高精度乘法

Problem Address:http://poj.org/problem?id=1001


【前言】


想随便找到题,于是翻出了收藏夹里的这道题。

嗯,高精度。

记得之前写过一个高精度乘法,但是不知道为什么错。

现在又一次面临高精度乘法。

还好最近刚写过一次,好似没出错,所以现在想试一下。

WA了一次,看discuss发现所给数字只是占了六位。改之。

同时发现了一个bug,于是debug。

然后AC。


【思路】


高精度。

先记录小数点的位数。再以整数求幂。最后再把小数点添加上去。

可以使用快速幂的方法。

但是,里面有很多需要注意的地方。

(1)所给小数只是占六个位,并不是一定是六个位都占满。同时可能存在没有小数点的情况。

(2)该小数可能是”.123","123.“,“0.123”等各种情况。

(3)其中的R和n均不为零。结果不可能为零。

(4)结果中可能存在前缀零个数很多的情况。多余的零要去掉,包括前缀零和后缀零。

(5)当没有小数或者整数部分时,应这样表示:“0.123” 表示为 “.123”,“123." 表示为 “123”。


【代码】


#include <iostream>
#include <cstring>
using namespace std;

const int size = 200;

struct num
{
	int n[size];
	int len;
	num()
	{
		memset(n, 0, sizeof(n));
		len = 1;
	}
};

void multiply(num &t, num s)//单个乘法
{
	int i,j;
	num a;
	for (i=0; i<t.len; i++)
	{
		for (j=0; j<s.len; j++)
		{
			a.n[i+j] += t.n[i] * s.n[j];
		}
	}
	for (i=0; i<size-1; i++)
	{
		if (a.n[i]>=10)
		{
			a.n[i+1] += a.n[i]/10;
			a.n[i] = a.n[i]%10;
		}
	}
	for (i=size-1; i>=0; i--)
	{
		if (a.n[i]!=0) break;
	}
	a.len = i+1;
	if (a.len==0)
		a.len = 1;
	for (i=0; i<size; i++)
	{
		t.n[i] = a.n[i];
	}
	t.len = a.len;
}

void output(num a, int d)//输出数字
{
	int i,j;
	if (a.len<=d) a.len = d+1;
	for (i=a.len-1; i>=d; i--)
	{
		if (a.n[i]!=0) break;
	}
	for ( ; i>=d; i--)
	{
		printf("%d", a.n[i]);
	}
	for (j=0; j<d; j++)
	{
		if (a.n[j]!=0) break;
	}
	if (j<d)
	{
		printf(".");
		for ( ; i>=j; i--)
		{
			printf("%d", a.n[i]);
		}
	}
	printf("\n");
}

num BigIntPow(num a, int n)//快速幂
{
	num t;
	t.n[0] = 1;
	while(n>0)
	{
		if (n&1) multiply(t, a);
		multiply(a, a);
		n >>= 1;
	}
	return t;
}


int main()
{
	char temp[10] = "";
	int n;
	int i,j;
	int decimal;
	int len;
	while(scanf("%s %d", temp, &n)!=EOF)
	{
		num t;
		len = strlen(temp);//以下处理读入的数字
		for (i=len-1; i>=0; i--)
		{
			if (temp[i]=='.') break;
		}
		if (i>=0)
		{
			decimal = (len-i-1)*n;
			for (i=len-1,j=0; i>=0; i--)
			{
				if (temp[i]=='.') continue;
				t.n[j] = temp[i] - '0';
				j++;
			}
			t.len = len-1;
		}
		else
		{
			decimal = 0;
			for (i=len-1,j=0; i>=0; i--,j++)
			{
				t.n[j] = temp[i] - '0';
			}
			t.len = len;
		}
		output(BigIntPow(t, n), decimal);
		memset(temp, 0, sizeof(temp));//存储空间清零,可以省去
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值