//===================================//
//
// poj:1001 浮点数求幂
// 完成时间:2010.09.07
//
//==================================//
#include <iostream>
#include <stdlib.h>
#include <string>
const int MAX_LEN = 150;
using namespace std;
int StringConvert(const string &str, int &t); //字符串转换int
int BigNumAdd(int *buf, int q, int ilen); //大数加法
unsigned int x1[MAX_LEN * 2 + 10];
unsigned int x2[MAX_LEN + 10];
unsigned int result[MAX_LEN * 2 + 10];
int main()
{
string R; //输入的实数
int N; //幂次方
while(cin >> R >> N)
{
int decialNum = 0; //保存小数点位数
int ilen = 0; //
int t = 0; //字符串转换完成int数组后保存数组长度
bool nozero = false; //用于不计算前导0 ilen保存数的长度
memset(x1, 0, sizeof(x1));
memset(x2, 0, sizeof(x2));
memset(result, 0, sizeof(result));
decialNum = StringConvert(R, t); //将字符串转换并返回小数点位数
for (int j=t-1; j>=0; j--)
{
//判断用于去除int数组中的前导0
if (x2[j] != 0)
{
nozero = true;
x1[j] = x2[j];
ilen++;
}
else
{
if (!nozero)
{
continue;
}
else
{
x1[j] = x2[j];
ilen++;
}
}
}
int iresultLen = 0; //计算结果的数组长度
int ixlen = ilen; //x1保存的是被乘数
if (N == 0) //任何数的0次方为1
{
cout << "1" << endl;
}
else if (N == 1) //任何数的1次方为其本身
{
if (decialNum >= ilen) //当小数位数大于数的长度时
{
//直接忽略前导0输出小数点
cout << '.';
//根据小数点和数字位数差来决定输出几个零
for (int b=0; b<decialNum-ilen; b++)
{
cout << '0';
}
//输出数组中保存的数
for (int c=ilen-1; c>=0; c--)
{
cout << x2[c];
}
}
else //当小数位数小于数的位数时
{
bool label = false; //用于判断小数点是否已打印
for (int d=ilen-1; d>=0; d--)
{
//当到达打印小数点的位置时打印小数点
if (d == decialNum - 1 && !label)
{
cout << '.';
d++;
label = true;
}
else
{
cout << x2[d];
}
}
}
cout << endl;
}
else //除了0次方和1次方以外的情况
{
int n = N; //保存次方数和初始小数点位数相乘用于计算最后小数点的位数
N--;
while (N--)
{
if (iresultLen) //当结果数组的长度为0时代表此时为第一次乘法
{
memset(x1, 0, sizeof(x1));
//将上一次的结果保存为被乘数以便进行下一次运算
for (int i=0; i<iresultLen; i++)
{
x1[i] = result[i];
ixlen = iresultLen;
}
}
memset(result, 0, sizeof(result)); //结果必须清零否则上次数据将被使用
//ilen保存乘数个位数,以确定做几次乘法
for (int q=0; q<ilen; q++)
{
int z = 0; //进位
int buf[MAX_LEN * 2 + 10] = {0}; //临时保存结果
for (int y=0; y<ixlen; y++)
{
int tmp;
tmp = x1[y] * x2[q] + z; //从各位开始做乘法,初始进位为0
buf[y] = tmp % 10; //求模取结果
z = tmp / 10; //除法取进位
}
int ibufLen = ixlen; //用于保存将传递的一次乘法结果的位数
if (z) //查看进位是否为0如果为0则不计算不为0则在结果的最高位的下一位赋值
{
buf[ixlen] = z;
++ibufLen;
}
iresultLen = BigNumAdd(buf, q, ibufLen); //将一次乘法结果与上次乘法结果相加并返回结果位数
}
}
if (decialNum * n >= iresultLen) //输出类似1次方的输出,区别为要考虑小数点位数
{
cout << '.';
for (int i=0; i<decialNum*n-iresultLen; i++)
{
cout << '0';
}
for (int l=iresultLen-1; l>=0; l--)
{
cout << result[l];
}
}
else
{
bool label = false;
for (int d=iresultLen-1; d>=0; d--)
{
if (d == decialNum * n - 1 && !label)
{
cout << '.';
d++;
label = true;
}
else
{
cout << result[d];
}
}
}
cout << endl;
}
}
return 0;
}
//字符串结果转换保存到int数组中,并返回数组元素个数和小数点位数
int StringConvert(const string &str, int &t)
{
int decialNum = 0;
bool label = false; //标识是否已经遇到非零的数
int iRsize = str.size();
//数据都从个位向高位保存
for (int i=iRsize-1; i>=0; i--)
{
char temp;
int k; //忽略了所有浮点数尾部的0以后有效值的开始位置
temp = str[i];
if (temp != '0') //判断字符是否为0
{
if (!label) //且遇0标识为false表示第一次遇到非0数
{
k = i;
label = true;
}
if (temp == '.')
{
if (i != iRsize - 1)
{
decialNum = k - i; //计算小数点的位数
}
}
else
{
x2[t++] = str[i] - '0';
}
}
else
{
if (!label)
{
continue;
}
else
{
x2[t++] = 0;
}
}
}
return decialNum;
}
//大数加法
int BigNumAdd(int *buf, int q, int ilen)
{
int j = 0; //进位
int i;
int k;
for (i=q, k=0; k<ilen; k++, i++)
{
int tmp;
tmp = result[i] + buf[k] + j; //从个位开始,模拟手算
result[i] = tmp % 10;
j = tmp / 10;
}
if (j)
{
result[i] += j;
i++;
}
return i;
}
poj 1001 浮点数高精度求幂
最新推荐文章于 2021-02-04 09:07:03 发布