您的位置:首页 > 其它

poj-1001 高精度幂

2013-03-24 15:05 260 查看
求高精度幂

Time Limit: 500MS Memory Limit: 10000K
Total Submissions: 114985 Accepted: 27919
Description
对数值很大、精度很高的数进行高精度计算是一类十分常见的问题。比如,对国债进行计算就是属于这类问题。

现在要你解决的问题是:对一个实数R( 0.0 < R < 99.999 ),要求写程序精确计算 R 的 n 次方(Rn),其中n 是整数并且 0 < n <= 25。
Input
T输入包括多组 R 和 n。 R 的值占第 1 到第 6 列,n 的值占第 8 和第 9 列。
Output
对于每组输入,要求输出一行,该行包含精确的 R 的 n 次方。输出需要去掉前导的 0 后不要的 0 。如果输出是整数,不要输出小数点。
Sample Input
95.123 12
0.4321 20
5.1234 15
6.7592  9
98.999 10
1.0100 12

Sample Output
548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201

 

解题时间:2013/3/23 - 2013/3/24

        

解题思路:

     用数组表示数串,每一个数组元素存储数串的一位。

     数字串反向存储,如123.456   存储为654321  记录长度和小数点的位置,这样存储是为了方便计算。

     所有的乘法都用累加来实现。

 

代码:

#include <stdio.h>

void ADD(int arr1[],int arr2[],int *L1,int L2,int *P1,int P2)
{
int temp;
int L;
int i;
if(*P1>=P2)
{
temp=*P1-P2;
L=*L1>(L2+temp)?*L1:(L2+temp);
for(i=temp; i<L; i++)
{
arr1[i]+=arr2[i-temp];
}
*L1=L;
}
else
{
temp=P2-*P1;
L=(*L1+temp)>L2?(*L1+temp):L2;
for(i=L-1; i>=0; i--)
{
if(i>=temp) arr1[i]=arr1[i-temp];
else arr1[i]=0;
}
for(i=0; i<L; i++)
{
arr1[i]+=arr2[i];
}
*L1=L;
*P1=P2;
}
//规范化
for(i=0; i<*L1; i++)
{
if(arr1[i]>=10)
{
arr1[i]-=10;
arr1[i+1]++;
}
}
if(arr1[i]==1)
*L1+=1;
}
//arr2复制到arr1
void COPY(int arr1[],int arr2[],int *L1,int L2,int *P1,int P2)
{
int i=0;
for(; i<L2; i++)
{
arr1[i]=arr2[i];
}
while(i<150)
{
arr1[i]=0;
i++;
}
*L1=L2;
*P1=P2;
}
//规范化得到t1,t2的值
void NORMALIZE(int arr[],int L,int P,int *t1,int *t2)
{
*t1=0,*t2=0;
int i;
for(i=0; (i<P-1)&&(arr[i]==0); i++)
{
*t1=*t1+1;
}
for(i=L; (i>=P)&&(arr[i-1]==0); i--)
{
*t2=*t2+1;
}
}
void SETZERO(int arr[],int *L,int *P)
{
int i;
for(i=0; i<*L; i++)
{
arr[i]=0;
}
*L=0;
*P=0;
}
int main()
{
char str[7];//输入的串
int n;
int sumNow[150] = {0};//当前值
int sumNowL=0,sumNowP=0;//串长度,不包括小数点,小数点位置如123.456为4
int sumLast[150] = {0};//每次幂之后的值
int sumLastL=0,sumLastP=0;
int sumTemp[150] = {0};//中间值
int sumTempL=0,sumTempP=0;
int s[6]= {0}; //输入的串
int sL,sP;
int i,j;
int t1,t2;

while(scanf("%s %d",str,&n)!=EOF)
{
SETZERO(sumLast,&sumLastL,&sumLastP);
SETZERO(sumTemp,&sumTempL,&sumTempP);
//将输入的串用数组的形式表示
sL=6;
sP=6;
j=0;
for(i=5; i>=0; i--)
{
if(str[i]=='.')
{
sL=5;
sP=6-i;
}
else
{
s[j]=str[i]-48;
j++;
}
}
//计算每次幂后的结果
COPY(sumNow,s,&sumNowL,sL,&sumNowP,sP);
COPY(sumLast,s,&sumLastL,sL,&sumLastP,sP);
n--;
while(n)
{
SETZERO(sumNow,&sumNowL,&sumNowP);
for(i=0; i<sL; i++)
{
if(s[i]==0)
continue;
COPY(sumTemp,sumLast,&sumTempL,sumLastL,&sumTempP,sumLastP);
for(j=1; j<s[i]; j++)
{
ADD(sumTemp,sumLast,&sumTempL,sumLastL,&sumTempP,sumLastP);
}
sumTempP=sumTempP+sP-i-1;//L是否要变
ADD(sumNow,sumTemp,&sumNowL,sumTempL,&sumNowP,sumTempP);
}
n--;
COPY(sumLast,sumNow,&sumLastL,sumNowL,&sumLastP,sumNowP);
}
NORMALIZE(sumNow,sumNowL,sumNowP,&t1,&t2);
for(i=sumNowL; i>0; i--)
{
if(t2)
{
t2--;
}
else
{
if(i>t1)
printf("%d",sumNow[i-1]);
}
if((i==sumNowP)&&(t1+1!=sumNowP))
{
printf(".");
}
}
printf("\n");
}
return 0;
}


 

 

 

 

 

 

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: