/*__________________________________________________POJ 1001题______________________________________________________ 求高精度幂 Time Limit: 500MS Memory Limit: 10000K Total Submissions: 69456 Accepted: 16252 Description: 对数值很大、精度很高的数进行高精度计算是一类十分常见的问题。比如,对国债进行计算就是属于这类问题。 现在要你解决的问题是:对一个实数R(0.0<R<99.999),要求写程序精确计算R的n次方(Rn),其中n是整数并且0<n<=25。 Input: 输入包括多组 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 **********************************************************************************************************/ /******************************************************************************************************* 做这个题关键要弄懂做乘法的过程(小学学的^-^), 例如:253*327,就是7个253 加 20个253 加 300个253,计算过程是 7*253=1771,模10的余数1作个位,177作进位;再2*253+177=683,模10的余数3作十位,68作进位;再3*253+68=827,模 10的余数是7,28作进位;犹豫乘数已乘尽,28模10的结果分别作千位,万位;就得结果82731 *******************************************************************************************************/ #include<iostream> #include<string> #include<stdlib.h> using namespace std; /* #include <fstream> fstream fin ("input.txt",ios::in); #define cin fin //*/ //计算 m乘以把n分段后得到的faciend,即faciend*m string Calculate(long faciend,string m) { string stepResult;//每次的结果 long product=0;//乘积 char remaining[2];//余数 long carry=0;//进位 for(int i=m.length()-1; i>=0; i--) { product=faciend*(m[i]-'0')+carry; sprintf(remaining,"%d",product%10); //itoa(product%10,remaining,10); carry=product/10; stepResult.insert(0,remaining); } while(carry) { sprintf(remaining,"%d",carry%10); //itoa(carry%10,remaining,10); stepResult.insert(0,remaining); carry/=10; } return stepResult; } //对串a和b中存放的大整数做加法 string Add(string a,string b) { char c; int i=a.length()-1, j=b.length()-1; string addResult; int remaining=0;//余数 int carry=0;//进位 for(; i>=0 && j>=0; i--,j--) { remaining=((a[i]-'0')+(b[j]-'0')+carry)%10; carry=((a[i]-'0')+(b[j]-'0')+carry)/10; c=(char)(remaining+'10'); addResult.insert((string::size_type)0,1,c);//注意用insert()插入单个字符的用法 } while(j>=0)//b比a长 { remaining=((b[j]-'0')+carry)%10; carry=((b[j]-'0')+carry)/10; c=(char)(remaining+'10'); addResult.insert((string::size_type)0,1,c); j--; } while(i>=0)//b比a长 { remaining=((a[i]-'0')+carry)%10; carry=((a[i]-'0')+carry)/10; c=(char)(remaining+'10'); addResult.insert((string::size_type)0,1,c); i--; } return addResult; } /******************************************************************************************************* 把乘数n拆分成long型能放下的一段一段faciend,分别与被乘数m相乘,结果相加 ********************************************************************************************************/ //进行大整数乘法的函数 string IntMultiple(string m,string n) { cout<<"*********************大整数乘法计算开始*************************"<<endl; int i=0;//统计n的位数是8的多少倍 long faciend;//每次从n中取的低位串转换成的long型 string result;//结果 string substr;//每次从n中取出的低位串 string sectionResult;//每次进行Calculate()后返回的串 const char *temp;//因为atoi()函数的参数只能是char *,所以先用个中间变量temp int flag=n.length()>8 ? 1 : 0;//标志n的位数是否大于8,据此判断是否需要分段计算 while(n.length()) { if(n.length() >8)//n中剩下的还够8位 { substr=n.substr(n.length()-8);//每次取n的低8位 temp=substr.c_str();//转换为const char *类型 faciend=atoi(temp);//再转换为long型 n.erase(n.length()-8);//取完后就删除,这样就可以用n的长度判断是否结束 } else//n中剩下的不够8位了 { temp=n.c_str(); faciend=atoi(temp);//再转换为long型 n="";//清空串,注意:删除n低位的字符一定要在atoi()函数转换以后,因为temp只是个指针,指向n中的低位字符, //但并没有实际存储n中的低位字符 } sectionResult=Calculate(faciend,m); if(flag)//原始输入的n的位数小于8时不需补'0' sectionResult.insert((string::size_type)sectionResult.length(),8*i,'0');//补8*i个'0' cout<<"第"<<i+1<<"步:"<<endl; cout<<" result: "<<result<<endl; cout<<" + "<<endl; cout<<"sectionResult: "<<sectionResult<<"=m*"<<faciend<<endl; result=Add(result,sectionResult); cout<<" = "<<endl; cout<<" result: "<<result<<endl<<endl; i++;//i统计取的是第几个8位段,据此每次进行Calculate后要补8*i个'0',注意:取的第一个低8位计算后不需补0, //所以i一定要在取完低8位后再加1,即要放在最后 } if(result=="")//若result为空,表示结果是0 result=="0"; cout<<"********************大整数乘法计算结束*************************"<<endl; return result; } //漏掉串s中的前导零 string OmitPreZeros(string s) { for(int i=0;s[i]=='0';)//去掉前导0 s.erase(i,1); return s; } //漏掉串s中的后导零 string OmitPostZeros(string s) { for(int i=s.length()-1;s[i]=='0';i--)//去掉后导0 s.erase(i,1); return s; } /****************************************************************************** 读入两个浮点数后的处理步骤是:1、去掉后导0,因为后导0是无任何意义的,并且影响对小数位数的统计。 2、统计小数位数。3、去掉小数点。4、去掉前导0,因为前导0会影响转化后的整数。5、计算大整数乘法。 6、给计算结果加小数点,若位数小于小数点个数,补零。7优化格式,去除可能的前后导零 若读入整数只需去掉前导0 ******************************************************************************/ //进行浮点数乘法的函数 string FloatMultiple(string m,string n) { string result; int sumDot=0;//总的小数位数 if(m.find('.')!=string::npos)//若m中有小数点 { m=OmitPostZeros(m); cout<<endl<<"去掉后导零后的m: "<<m<<endl;//去掉后导0 sumDot+=m.length()-m.find('.')-1;//记录小数位数 m.erase(m.find('.'),1); //去掉m,n中的小数点 cout<<"去掉小数点后的m: "<<m<<endl; } if(n.find('.')!=string::npos) { n=OmitPostZeros(n); cout<<endl<<"去掉后导零后的n: "<<n<<endl; sumDot+=n.length()-n.find('.')-1; n.erase(n.find('.'),1); cout<<"去掉小数点后的n: "<<n<<endl; cout<<endl<<"总的小数位数: "<<sumDot<<endl<<endl; } m=OmitPreZeros(m); if(m=="")//m全是0 m="0"; n=OmitPreZeros(n); if(n=="")//n全是0 n="0"; cout<<"去掉前导零后的m: "<<m<<endl; cout<<"去掉前导零后的n: "<<n<<endl<<endl; //然后直接调用写好的计算大整数的函数IntMultiple() result=IntMultiple(m,n); if(sumDot)//若有浮点数参与运算,在大整数的计算结果上加小数点 { if(sumDot<=result.length())//小数位数小于等于结果的位数,不用在前面补0 result.insert((string::size_type)(result.length()-sumDot),1,'.'); else { result.insert((string::size_type)0,sumDot-result.length(),'0'); result.insert((string::size_type)0,1,'.'); } } cout<<endl<<"加小数点后: "<<result<<endl<<endl; if(sumDot)//若有浮点数参与运算,去掉可能的后导0,若是整数可不能去掉 result=OmitPostZeros(result); cout<<"去掉可能的后导零: "<<result<<endl; cout<<"********************大浮点数乘法计算结束*************************"<<endl; return result; } int main() { int i,count=0; string R; string result; string resultSet[20]; int n; cout<<"请依次输入浮点数和要求的幂值:"<<endl; while(cin>>R>>n) { if(n==0)//任何数的0次幂都是1 cout<<1<<endl; else if(n==1)//1次幂不用计算,进行格式优化后输出 { result=R; if(result.find('.')!=string::npos)//若是小数,去掉后导0 result=OmitPostZeros(result); result=OmitPreZeros(result);//整数小数都要去掉前导0 if(result[result.length()-1]=='.')//若result最后有个小数点,去掉它 result.erase(result.length()-1,1); if(result=="")//若result成了空串,说明是0 result="0"; cout<<result<<endl; } else { result=R; for(i=1;i<n;i++) result=FloatMultiple(result,R); cout<<result<<endl; } cout<<"请依次输入浮点数和要求的幂值:"<<endl; //system("pause"); } return 0; }