This problem requires that you write a program to compute the exact value of R nwhere R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.
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
s is a string and n is an integer
C++ while(cin>>s>>n) { ... } c while(scanf("%s%d",s,&n)==2) //to see if the scanf read in as many items as you want /*while(scanf(%s%d",s,&n)!=EOF) //this also work */ { ... }
思路:这道题目考查高精度乘法的计算。
要解决这道题目并不能使用cmath里的pow函数,而必须自己模拟乘法的计算过程,以实现高精度结果的输出。
所幸输入的底数一定是5位数,这给我们创造了一点方便。
我们可以将底数以字符串的形式读入,然后计算出结果中小数点应该在多少位,比如第一个结果应该是3*12=36。
关键的部分在于数据的处理,这里我的办法是倒序去掉小数点逐位存储,比如95.123,最后应该是用一个大小为5的数组存储为[3][2][1][5][9],每个单元只存一个数位。这里涉及到存储类型的问题,为了计算方便,最好用short类型的数组。
存储结果的数组需要开到150,我没有精确计算,大概是这么大,我选择160。
为了计算方便,我们不把数字多余的0去掉,而是在最后判断小数点的位置,然后输出该输出的数位。
每次乘法,都是用题目给的r乘上你上一次得出的结果,如果是第一次计算,那么就是r,计算的结果直接加到一个初始化为0的160大小的数组里面,注意是加。乘法的过程很容易模拟出来,就是让乘数让乘数第一位把你的结果的所有位乘一遍,然后再让第二位乘,注意加进数组时,有一个偏移量,乘法竖式都是这么写的,大家体会下。
为什么使用倒序存储的数组呢,想想上面对竖式的模拟就很容易明白了,从0位开始乘,结果也从0位开始存,非常方便。这样得出的结果也是倒序的。
输出结果时要小心,因为数组中存储的数位是倒序的,且没有小数点,需要计算从两边向中间的小数点方向第一个不为0数的位置,这是为了避免输出不必要的0而导致WA。
给出一个计算过程演示:
比如输入为1.0002 3
20001
× 2
------------
40002
此时结果数组中存储的是40002
20001
× 0
------------
40002
00000
此时结果数组中存储的是40002中间省略两步
20001
× 1
------------
40002
00000
00000
00000
20001
此时结果数组中存储的是400040001
400040001
× 2------------------
这里我就不计算了,最后结果数组里面存的是8000210060001
根据4*3=12,可以知道小数点应插在12号位,也就是11号位后面
800021006000.1
两边向中间,第一个不为0的数恰好就是两边,输出为
1.000600120008
代码:
#include<iostream> #include<string> #include<string.h> using namespace std; int main() { string r; int n; const int len=160; int result[len],a[len],b[6]; while(cin>>r>>n) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(result,0,sizeof(result)); int i,j,signi=0;//signi标记小数点的位置 size_t pos=r.find(".");//寻找小数点的位置 if(pos!=string::npos)//判断是否是整数 signi=(5-pos)*n;//记录有多少位小数 for(i=5,j=0; i>=0; i--) { if(r[i]!='.') { result[j]=a[j]=b[j]=r[i]-'0'; j++; } } while(n>=2)//注意n=1的情况 { n--; memset(result,0,sizeof(result)); for(i=0; i<5; i++) { for(j=0; j<len; j++) { if(!b[i]) break; result[i+j]+=a[j]*b[i]; result[i+j+1]+=result[i+j]/10;//处理进位 result[i+j]=result[i+j]%10; } } memcpy(a,result,sizeof(result));//转存结果,以便下次计算 // for(i=0; i<len; i++) // a[i]=result[i]; } int fronti=-1; for(i=len-1; i>=signi; i--)//去除前面多余的0 { if(result[i]) { fronti=i; break; } } int lasti=-1; for(i=0; i<signi; i++)//去除后面多余的0 { if(result[i]) { lasti=i; break; } } if(fronti!=-1) { for(i=fronti; i>=signi; i--) cout<<result[i]; } if(lasti!=-1) { cout<<"."; for(i=signi-1; i>=lasti; i--) cout<<result[i]; } cout<<endl; } return 0; }