这道题属于高精度乘法运算,要求输入一个实数R一个指数N,求实数R的N次方,因为R有5个数位,而N又特别大,所以用C++自带的数据类型放不下.
解题思路是经过数组储存每次乘积结果和底数的每一位数,按照乘法上下算式的方法,计算底数乘数数组每一位与临时结果数组的每一位的乘积,(由于算术运算中是从数的后面往前算的,这里存储数时要先倒序,输出时再颠倒过来,)而后偏移相加,判断得出的临时结果数组的每一位是否大于9,经过除法和取模实现进位和取余.至此得出一个有不少无效数位的结果数组(不少无效的0).
最后判断结果数组的每一位是否为0,先输出小数点前面的数,后输出小数点后面的数,最终得出乘法结果.
这个题目实际上考的是高精度乘法,高精度的其余运算和这个差很少,原理都是同样的.
ios
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.数组
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.函数
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.ui
95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12spa
If you don't know how to determine wheather encounted the end of input:
s is a string and n is an integercode
#include<iostream> #include<cstring> using namespace std; int main() { string r; //底数 int n,dianwei; //指数,小数点位置 const int len=200; //数位长度 short result[len],jieguo[len],chengshu[6]; //最终结果,临时结果,底数乘数 while(cin>>r>>n) { //初始化 for(int i=0;i<len;++i) jieguo[i]=result[i]=0; for(int i=0;i<6;++i) chengshu[i]=0; dianwei=0; //获得底数小数点位置 size_t pos = r.find('.'); //若是底数中有小数点 获取小数点后面有多少位数 if(pos!=string::npos) dianwei=(5-pos)*n; //把底数中全部不是小数点的数字挑出来转换为int并赋给最终结果,临时结果,底数乘数 获得的是3个5位先后颠倒的数组 之因此颠却是由于乘法是从后往前乘的 for(int i=5,j=0;i>=0;--i) { if(r[i]!='.') { jieguo[j]=result[j]=chengshu[j]=r[i]-'0'; ++j; } } //当指数大于1时 进行如下运算 等于1时跳过这段程序直接输出 while(n>=2) { --n; //初始化最终结果数组 for(int i=0;i<len;++i) result[i]=0; for(int i=0;i<5;++i) //从底数乘数的每一位 { //底数乘数每位数和临时结果每位数相乘的临时变量 int temp; for(int j=0;j<len;++j) //乘以临时结果的每一位 { //若是底数乘数某一位是0 不必乘下去了 跳出当前循环 if(chengshu[i]==0) break; temp=chengshu[i]*jieguo[j]; //i+j实现乘法相加时的移位 result[i+j]+=temp; //++t遍历全部结果数组中大于9的数 用除法和取模实现进位和余数 for(int t=i+j;result[t]>9;++t) { result[t+1]+=result[t]/10; result[t]=result[t]%10; } } } //把一次乘法后的结果赋给临时结果来进行下次乘方 for(int i=0;i<len;++i) jieguo[i]=result[i]; } //获取最终结果从后数第一个不为0的数做为第一个数的标志位 之因此从后数 是由于以前颠倒的数要颠倒回来了 int firstindex=-1; for(int i=len;i>=dianwei;--i) { if(result[i]>0) { firstindex=i; break; } } //获取 最终结果从前数第一个不为0的数做为最后一个数的标志位 int lastindex=-1; for(int i=0;i<dianwei;++i) { if(result[i]>0) { lastindex=i; break; } } //若是最终结果数组中不全是0 倒序输出结果数组中小数点前面的数 if(firstindex!=-1) { while(firstindex>=dianwei) { cout<<result[firstindex]; --firstindex; } } //若是最终结果数组中不全是0 倒序输出结果数组中小数点后面的数 if(lastindex!=-1) { cout<<'.'; --dianwei; while(dianwei>=lastindex) { cout<<result[dianwei]; --dianwei; } } cout<<endl; } }
#附录:blog
#include <iostream> #include <cstring> using namespace std; const int N=100;//最多100位 int main() { int a[N+1],i; string s1; cin>>s1;//数s1 memset(a,0,sizeof(a)); //数组清0 a[0]=s1.length(); //位数 for(i=1;i<=a[0];i++) { a[i]=s1[a[0]-i]-'0';//将字符转为数字并倒序存储. } return 0; }
#include <iostream> using namespace std; const int N=100;//最多100位 int main() { int a[N+1],i,s,key; cin>>key;//数key memset(a,0,sizeof(a)); //数组清0 i=0;//第0位 while(key) //当key大于0 { a[++i]=key%10;//取第i位的数 key=key/10; } a[0]=i; //共i位数 return 0; }
如下程序都只写函数,不写完整程序,全部高精度数存储都知足上述约定。ip
int compare(int a[],int b[]) //比较a和b的大小关系,若a>b则为1,a<b则为-1,a=b则为0 { int i; if (a[0]>b[0]) return 1;//a的位数大于b则a比b大 if (a[0]<b[0]) return -1;//a的位数小于b则a比b小 for(i=a[0];i>0;i--) //从高位到低位比较 { if (a[i]>b[i]) return 1; if (a[i]<b[i]) return -1; } return 0;//各位都相等则两数相等。 }
int plus(int a[],int b[]) //计算a=a+b {int i,k; k=a[0]>b[0]?a[0]:b[0]; //k是a和b中位数最大的一个的位数 for(i=1;i<=k;i++) { a[i+1]+=(a[i]+b[i])/10; //如有进位,则先进位 a[i]=(a[i]+b[i])%10; //计算当前位数字,注意:这条语句与上一条不能交换。 } if(a[k+1]>0) { a[0]=k+1; //修正新的a的位数(a+b最多只能的一个进位) } else { a[0]=k; } return 0; }
int gminus(int a[],int b[]);//计算a=a-b,返加符号位0:正数 1:负数 { int flag,i flag=compare(a,b); //调用比较函数判断大小 if (falg==0)//相等 { memset(a,0,sizeof(a));return 0; //若a=b,则a=0,也可在return前加一句a[0]=1,表示是 1位数0 } if(flag==1) //大于 { for(i=1;i<=a[0];i++) { if(a[i]<b[i]){ a[i+1]--;a[i]+=10;} //若不够减则向上借一位 a[i]=a[i]-b[i]; } while(a[a[0]]==0) a[0]--; //修正a的位数 return 0; } if (flag==-1)//小于 则用a=b-a,返回-1 { for(i=1;i<=b[0];i++) { if(b[i]<a[i]){ b[i+1]--;b[i]+=10; //若不够减则向上借一位 } a[i]=b[i]-a[i];} a[0]=b[0]; while(a[a[0]]==0) a[0]--; //修正a的位数 return -1; } }
int multi1(int a[],long key) //a=a*key,key是单精度数 { int i,k; if (key==0){memset(a,0,sizeof(a));a[0]=1;return 0;} //单独处理key=0 for(i=1;i<=a[0];i++) { a[i]=a[i]*key;//先每位乘起来 } for(i=1;i<=a[0];i++) { a[i+1]+=a[i]/10;a[i]%=10; //进位 } //注意上一语句退出时i=a[0]+1 while(a[i]>0) { a[i+1]=a[i]/10;a[i]=a[i]%10;i++;a[0]++]; //继续处理超过原a[0]位数的进位,修正a的位数 } return 0; }