POJ1001

C++源代码:

//	Exponentiation
//	copy


#include <iostream>

using namespace std;



// 计算 多 乘以 一 的情况,例如,1234 * 4

// many:    多位数

// one:        单位数

// offset:    乘10偏移

// return:    返回计算结果

char * MMO(char * many, char one, int offset)

{

	int mLength;    // 多位数的长度

	char * res;        // 计算结果

	int i;

	int n1, n2;        // 逐位相乘的两个乘数

	int sres;        // 逐位相乘的积

	int carry;        // 进位

					  // 初始化各变量

	n2 = one - 48;

	carry = 0;

	// 获取多位数的位数

	mLength = -1;

	while (many[++mLength]);

	// 计算运算结果的位数并分配空间

	res = new char[mLength + 1 + offset + 1];

	// 初始化结果为0

	for (i = 0; i < mLength + offset + 1; i++)

	{

		res[i] = '0';

	}

	res[mLength + offset + 1] = 0;    // 字符串结尾

									  // 逐位相乘

	for (i = mLength - 1; i >= 0; i--)

	{

		n1 = many[i] - 48;

		// 1. 将两个乘数相乘

		sres = n1 * n2;

		// 2. 将结果再加上进位

		sres += carry;

		// 3. 将计算得到的结果分成10进位和个位

		res[i + 1] = sres % 10 + 48;    // 个位,直接存在计算结果中

		carry = sres / 10;        // 十位,保存在进位中

	}

	// 将进位存入最高位

	res[0] = carry + 48;

	// 返回计算结果

	return res;

}



// 计算两个多位数相加,将结果存入m1,并释放m2

// m1:        多位数1

// m2:        多位数2

// 需要注意的是,多位数1的位数一定要大于等于两数和的位数

void MPM(char * m1, char * m2)

{

	int l1, l2;        // 两个多位数的长度

	char * res;        // 计算结果

	int i;

	int lRes;        // 结算结果的长度

	int carry;        // 进位

	int n1, n2;        // 两个单位加数位

					   // 初始化变量

	carry = 0;

	// 获取两个加数的长度

	l1 = l2 = -1;

	while (m1[++l1]);

	while (m2[++l2]);

	// 实现两数相加

	for (i = 1; i <= l1; i++)

	{

		n1 = m1[l1 - i] - 48;

		if (l2 - i < 0)

			n2 = 0;

		else

			n2 = m2[l2 - i] - 48;

		// 计算两数和并存入m1中

		m1[l1 - i] = (n1 + n2 + carry) % 10 + 48;

		carry = (n1 + n2 + carry) / 10;

	}

	// 将进位存入首位

	if (l1 != l2)

		m1[l1 - l2 - 1] = carry + 48;

	// 释放被加数

	delete m2;

}



// 计算两个多位数相乘

// m1:        乘数1

// m2:        乘数2

// return:    返回两数相乘结果

char * MMM(char * m1, char * m2)

{

	int l1, l2;        // 两个多位数的长度

	char * res;        // 计算结果

	int i;

	int lRes;        // 结算结果的长度

	int carry;        // 进位

	int n1, n2;        // 两个单位乘数位

					   // 初始化变量

	carry = 0;

	// 获取两个加数的长度

	l1 = l2 = 0;

	while (m1[l1++]);

	while (m2[l2++]);

	l1--;

	l2--;

	// 为了减少计算乘法次数,将位数较少的数作为乘数

	if (l1 < l2)

	{

		char * tp = m2;

		m2 = m1;

		m1 = tp;

		int tpl = l2;

		l2 = l1;

		l1 = tpl;

	}

	// 为计算结果分配空间

	// 两数相乘的结果的位数 = 被乘数的位数 + 乘数的位数

	lRes = l2 + l1;

	res = new char[lRes + 1];

	// 初始化结果为0

	for (i = 0; i < lRes; i++)

	{

		res[i] = '0';

	}

	res[lRes] = 0;

	// 进行逐位相乘

	for (i = 1; i <= l2; i++)

	{

		char * sr = MMO(m1, m2[l2 - i], i - 1);

		MPM(res, sr);

	}

	// 返回计算结果

	return res;

}



// 计算 R 的 N 次方,R和N均为整数

// return: 返回未修饰的计算结果

char * RN(char * R, int N)

{

	if (N < 2)

		return R;

	char * res = MMM(R, R);

	for (int i = 0; i < N - 2; i++)

	{

		char * res2 = res;

		res = MMM(res, R);

		delete res2;

	}

	return res;

}



// 规范化输出计算结果,加上小数点,并去掉多余的0

void OutputRes(char * res, int pNum)

{

	int lRes;

	int i;

	bool flag;

	// 获取输出字符串的长度

	lRes = -1;

	while (res[++lRes]);



	// 计算输出区间

	flag = false;

	if (pNum > 0)

	{

		// 过滤首尾不用输出的0

		for (i = 0; i < lRes - pNum; i++)

		{

			if (res[i] != '0')

				break;

			else

				res[i] = '#';

		}

		for (i = 1; i <= pNum; i++)

		{

			if (res[lRes - i] != '0')

				break;

			else

				res[lRes - i] = '#';

		}

		if (i > pNum)        // 小数部位不用输出

			flag = true;

	}
	else {

		flag = true;

		for (i = 0; i < lRes; i++)

		{

			if (res[i] != '0')

				break;

			else

				res[i] = '#';

		}

		for (i = 1; i <= lRes; i++)

		{

			if (res[lRes - i] != '0')

				break;

			else

				res[lRes - i] = '#';

		}

	}

	// 输出结果

	for (i = 0; i < lRes; i++)

	{

		if ((i == lRes - pNum) && (!flag))

			cout << ".";

		if (res[i] != '#')

		{

			cout << res[i];

		}



	}

	cout << endl;

}



int main() {

	char R[10], Rin[10];        // 读入的乘幂运算的底

	int N;            // 读入的乘幂运算的指数

	int pNum;        // 读入的小数位数

					 // 读入并计算

	while (cin >> Rin >> N)

	{

		// 获得小数点的位数,并获取去掉小数点后的整数

		int l;

		int ll;

		l = ll = 0;

		pNum = -1;

		while (Rin[l])

		{

			if (Rin[l] == '.')

			{

				pNum = l + 1;

			}
			else {

				R[ll++] = Rin[l];

			}

			l++;

		}

		R[ll] = 0;

		if (pNum != -1)

			pNum = l - pNum;

		else

			pNum = 0;

		pNum = pNum * N;

		// 计算并输出结果

		char * s = RN(R, N);

		OutputRes(s, pNum);

		if (s != R)

			delete s;

	}

	return 0;

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值