求幂
总提交:390 测试通过:98
描述
求R的n次幂(0.0<r<99.999,0<n<=25)
输入
每行输入两个数R和n
R值占1-6列,n占8-9列
输出
对应于每一行输入,输出R的n次幂
前导的0不要输出
无意义的0不要输出
如果结果是一个整数,不要输出小数点
最后一行是空行样例输入
95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12
样例输出
548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201
题目来源
POJ
分析:
大数运算,涉及小数点和0的问题,有些复杂。
老方法输入字符串转化成int型数组,这里r是6位的,n不重要,因为空格结束,所以用循环
while(scanf("%s %d",&s,&n) != EOF)
将6位的char型数组转换成int型数组,注意:数组开6位出错,因为还有一个结束符,索性直接开10。为了输出考虑,记录小数点后面的数的个数point。
考虑到大数相乘时数组下标从0开始,将int型数组逆序。
之后大数相乘,将int数组a拷贝到int数组b,方便传递参数。(写法有很多,感觉写的好烦)num为一开始输入的字符串里数字的个数,不包括0.0001中前面无意义的0,每次乘以b数组,数组的个数num <= num+6,因为b数组长度小于6 。
大数相乘:
void fun(int a[], int b[], int num)
{
int mul[10000] = {0};
for(int i=0;i<num;i++)
for(int j=0;j<5;j++)
mul[i+j] += a[i] * b[j];
for(int i=0;i<num+6;i++) // +6 足矣
{
mul[i+1] += mul[i] / 10;
mul[i] = mul[i] % 10;
}
for(int i=0;i<num+6;i++) // 再赋予a
a[i] = mul[i];
}
每次乘完一个b数组,将得到的乘积数组再返回给a,循环n-1次。最后得到的最终数组是逆序的,且前后有一些无效的0。
Eg:95.123 12 得到的为:12725896912276............................651884500000000000
要输出的是:548815620517731830194541.899025343415715973535967221869852721
只要输入的小数点后面不是1.1100这种情况,首位一定非0。
最重要的是输出。
小数点后的位数为point*n,还有一种特殊情况:小数点后位数中有无效的0。原因是1.1100记录的point为4,则point*n=4n,但是其实只要输出2n,因为后面的0无效。
for(i=num-1;i>=0;i--)
if(a[i]!=0) break;
此时i为总的数字的位数。
if(point>i) // .xxxxx
{
printf("."); // 全在小数点右边
//
for(tmp=0;tmp<num;tmp++) // 右边多余的0不输出
if(a[tmp]!=0) break;
//
for(int k=point-1;k>=tmp;k--) // 逆序输出
{
printf("%d",a[k]);
}
}
else // xxxx.xxxx 或者 xxxx
{
for(;i>point-1;i--) // 打印小数点左边的数 条件 i>point-1 保证小数point个
{
printf("%d",a[i]);
}
//
for(tmp=0;tmp<num;tmp++) // 小数点右边第一个非0的下标 tmp
if(a[tmp]!=0) break;
//
if(i>=tmp) // 存在小数
printf(".");
for(;i>=tmp;i--)
printf("%d",a[i]);
}
完整代码:
#include<stdio.h>
//求幂
void fun(int a[], int b[], int num)
{
int mul[10000] = {0};
for(int i=0;i<num;i++)
for(int j=0;j<5;j++)
mul[i+j] += a[i] * b[j];
for(int i=0;i<num+6;i++) // +6 足矣
{
mul[i+1] += mul[i] / 10;
mul[i] = mul[i] % 10;
}
for(int i=0;i<num+6;i++) // 再赋予a
a[i] = mul[i];
}
int main()
{
char s[10];
int n;
while(scanf("%s %d",&s,&n) != EOF)
//while(cin>>s>>n)
{
int a[10000] = {0};
int num= 0,point;
for(int i=0;i<6;i++)
{
if(num == 0 && s[i] == '0') // 首位为0
{
continue;
}
if(s[i] != '.')
a[num ++] = s[i] - '0'; // m.数字 != 0
if(s[i] == '.')
point = 5 - i; // 小数点后面几位 1.0100
}
//逆序
for(int i=0;i<num/2;i++)
{
int tmp = a[i];
a[i] = a[num - i - 1];
a[num -i -1] = tmp;
}
//start!
//拷贝数组a到数组b,作乘数
int b[5];
for(int i=0;i<5;i++)
b[i] = a[i];
//循环求幂
for(int i=0;i<n-1;i++)
{
fun(a, b, num);
num = num + 6;
}
//输出重点! 依据小数点后数的个数
point = point * n; // 小数点后面几位
int i,tmp;
for(i=num-1;i>=0;i--) // num-1 ~ 0; 第一个非0的是先输出的(1.23456 中的1)
if(a[i]!=0) break;
if(point>i) // .xxxxx
{
printf(".");
//
for(tmp=0;tmp<num;tmp++)
if(a[tmp]!=0) break;
//
for(int k=point-1;k>=tmp;k--) // 逆序输出
{
printf("%d",a[k]);
}
}
else // xxxx.xxxx or xxxx
{
for(;i>point-1;i--) // 打印小数点左边的数 条件 i>point-1 保证小数point个
{
printf("%d",a[i]);
}
//
for(tmp=0;tmp<num;tmp++) // 多余的0无需输出
if(a[tmp]!=0) break;
//
if(i>=tmp) // 存在小数
printf(".");
for(;i>=tmp;i--)
printf("%d",a[i]);
}
printf("\n");
}
return 0;
}