题目
Description
Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems
This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.
Input
The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9
Output
The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don’t print the decimal point if the result is an integer.
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
解题思路
1、首先需要了解整数的高精度乘法
https://blog.csdn.net/qiongyaoxinpo/article/details/89378799
2、再这基础上了解整数的高精度指数乘法
https://blog.csdn.net/qiongyaoxinpo/article/details/89394674
3、在理解了高精度的指数乘法之后,剩下的就是对输入数据的判断以及数据的输出格式
4、判断是否为小数的最简单方法就是判断是否输入了小数点,若输入为整型,则按照上述已实现的方法进行输出即可,若为小数,则将需将小数点去掉,转换为新的字符串,并记录小数点的位置
5、以下均为小数的处理思路。去除字符串中小数点后的无效0以及去除字符串种小数有效数字前的无效0
6、带入高精度指数乘法中得到结果
7、以小数形式进行输出,分3种情况进行讨论
小数点位置n阶后的位数等于高精度指数乘法得到结果的位数,处理方法为:先输出小数点,后依次输出结果
小数点位置n阶后的位数大于高精度指数乘法得到结果的位数,处理方法为:先输出小数点,补齐缺失位置的0,后依次输出结果
小数点位置*n阶后的位数小于高精度指数乘法得到结果的位数,处理方法为:依次输出结果,在相应小数点位置补上小数点
测试样本
除了POJ1001给出的6组样本外,并不一定能够被accepted,更需要其他的边缘数据进行测试,博主在完成程序之后,被以下2组数据给拯救:1、r=0.01 n=1; 2、r = 10.000 n = 1;
程序
以下程序能够直接在vs2015社区版中实现,并且被POJ1001accepted,关键步骤都有详细注释
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
using namespace std;
#define Length 6
int *Str2int(char *str);
char *Int2str(int *num, int len);
char *Multi(char *s1, char *s2)
{
char *s;
int i, j, *c, *a, *b;
int len, la, lb;
la = strlen(s1);//统计字符串长度,不包括结束符'\0'
lb = strlen(s2);
a = Str2int(s1);//字符转整型
b = Str2int(s2);
len = la + lb;
s = (char *)malloc((len) * sizeof(char));
c = (int *)malloc((len) * sizeof(int));
memset(c, 0, sizeof(int)*len);
memset(s, 0, sizeof(char)*len);
/*高精度乘法的重点,按照人手工进行乘法运算的方式,通过进位的方法计算结果的每一位的值*/
for (i = 0; i<la; i++)//整数a的每一位与b的所有位分别相乘
for (j = 0; j < lb; j++)
{
c[i + j] += a[i] * b[j];//在c[i+j]的位置加上a的第i位与b的第j位的积
c[i + j + 1] += c[i + j] / 10;//在下一位的位置进位
c[i + j] = c[i + j] % 10;//在当前位置保留除以10后余数
}
s = Int2str(c, len);//整型转字符
return s;
}
char *Exp(char *s, int n)
{
char *d;
int i, lens, pos = -1, j = 0,lend,zn,lent,k;
char *dec;
lens = strlen(s);
d = (char *)malloc((lens*n) * sizeof(char));
dec = (char *)malloc((lens*n) * sizeof(char));
memset(dec, 0, sizeof(char)*lens*n);
memset(d, 0, sizeof(char)*lens*n);
for (i = 0; i < lens; i++)//判断是否为小数,若有小数点则记录位置
if (s[i] == '.')
pos = lens - i - 1;
if (pos != -1)//若有小数点,则将小数点清除,否则不进行操作
{
for (i = 0; i < lens; i++)
if (s[i] != '.')
dec[j++] = s[i];
dec[j] = '\0';
lent = strlen(dec);
k = pos;
for (i = 0; i < k; i++)//去掉小数点后面无效的0
if (dec[lent - i -1] == '0')
{
dec[lent - i -1] = '\0';
pos--;
}
else
break;
dec = dec + strspn(dec, "0");//除去小数前面无效的0
//strspn:检索字符串realNumString中第一个不在字符串"0"中出现的字符下标
strcpy(s, dec);
}
if (n == 1)
d = s;
else if (n>=2)//若阶次大于2,则进行n-1次自身相乘过程
{
d = s;
for (i = 0; i < n - 1; i++)
{
d = Multi(d, s);//n-1次高精度乘法过程
}
}
lend = strlen(d);
if (lend == pos*n)//小数点位置*n阶后的位数等于高精度指数乘法得到结果的位数
{
j = 0;
dec[j] = '.';
for (i = 0; i < lend; i++)
{
dec[++j] = d[i];
}
dec[++j] = '\0';
}
else if (lend < pos*n)//小数点位置*n阶后的位数大于高精度指数乘法得到结果的位数
{
j = 0;
zn = pos*n - lend;
dec[j] = '.';
for (i= 0; i<zn; i++)
dec[++j] = '0';
for (i = 0; i < lend; i++)
{
dec[++j] = d[i];
}
dec[++j] = '\0';
}
else//小数点位置*n阶后的位数小于高精度指数乘法得到结果的位数
{
j =0 ;
zn = lend - pos * n;
for (i = 0; i < lend; i++)
if (i == zn)
{
dec[j++] = '.';
dec[j++] = d[i];
}
else
dec[j++] = d[i];
dec[j] = '\0';
}
return dec;
}
int main()
{
char *s1, *s;//指针为实参,可以认为是全局变量
int n;
s1 = (char *)malloc(Length * sizeof(char));//使用指针进行操作时,需要先分配内存
memset(s1, 0, sizeof(char)*(Length));//初始化分配的内存,置0
while (cin >> s1 >> n)
{
s = Exp(s1, n);//指数乘法
cout << s << endl;
}
}
int *Str2int(char *str)
{
int len, i;
int *num;
len = strlen(str);
num = (int *)malloc(len * sizeof(int));
memset(num, 0, len * sizeof(int));
for (i = 0; i < len; i++)//对每一位字符进行倒序存放
num[i] = str[len - i - 1] - '0';//以ASCII码值进行相减,再转换成整型
return num;
}
char *Int2str(int *num, int len)
{
int i;
char *res;
res = (char *)malloc(len * sizeof(char));
memset(res, 0, len * sizeof(char));
while (num[len - 1] == 0 && len>1)//2个数想乘,结果位数必定小于等于2者位数之和
{ //大于等于2者位数之和-1
len--;
}
for (i = 0; i < len; i++)//以ASCII码值进行相加,再转换乘字符串形式
{
res[i] = num[len - 1 - i] + '0';
}
res[len] = '\0';
return res;
}