POJ1001 Exponentiation【高精度乘方】
来源:互联网 发布:java xbootclasspath 编辑:程序博客网 时间:2024/04/25 06:09
题目:
Description
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
Output
Sample Input
95.123 120.4321 205.1234 156.7592 998.999 101.0100 12
Sample Output
548815620517731830194541.899025343415715973535967221869852721.0000000514855464107695612199451127676715483848176020072635120383542976301346240143992025569.92857370126648804114665499331870370751166629547672049395302429448126.76412102161816443020690903717327667290429072743629540498.1075960194566517745610440100011.126825030131969720661201思路:
对数值很大、精度很高的数进行高精度计算是一类十分常见的问题。
现在要你解决的问题是:对一个实数R(0.0 < R < 99.999),要求写出程序精确计算R的n次方(Rn),其中n是整数并且0 < n <= 25。
输入包括多组R和n。R的值占第1到第6列,n的值占第8和第9列。
对于每组输入,要求输出一行,该行包含精确的R的n次方。输出需要去掉前导的0和后面不要的0。如果输出是整数,不要输出小数点。
因为c++的double类型根本表示不了这么长的结果,所以得手动写乘方。
我的解法不能算大数相乘的通用算法, 而只是针对题目中(0.0 < R < 99.999)的trick. 因R位数很小, 所以本算法思路是把R扩大倍数而转成整数(99.999 -> 99999), 然后把每次乘积累加到结果数组中。算法比较简单。时间在0ms到16ms之间波动。
代码:
#include <iostream>#include <string>using namespace std;int len; // total length of exponentiation result存储乘方结果的总长度int product[126] = {0}; //存储结果,最大长度为5*25+1=126(5是99.999有5个数字,25是n的最大值,+1是加的小数点)(可以试一下,99.999的平方是10个数字+一个小数点哦)void multiply(int a[], int n){ int i; int carry = 0; // a carry number in multiplying for (i = 0; i < len; i++){ int temp = a[i]*n + carry; a[i] = temp % 10; carry = temp / 10; } while (carry){ a[i] = carry % 10;i++; carry /= 10; } len = i;}int main(){ int n; // power n char s[6]; // real number R, at most the length is 6 while (cin>>s>>n){ int position=0, i=0, num=0, j=0; for (i=0; i<strlen(s); i++) { if (s[i] == '.'){ position = (strlen(s) - 1 - i) * n; // calculate decimal point position in // in R^n,因为结果数组是倒着放的,所以.的位置要用小数来算 } else{ num = num*10 + s[i] - '0'; // transfer float to integer } } // product calculation product[0]=1; len = 1; for (i = 0; i < n; i++){ multiply(product, num); } // format output if (len <= position){ // product is less than 1 printf("."); // print decimal point for (i=0; i<position-len; i++){ printf("0"); // print zero between decimal point and decimal } j = 0; while (product[j] == 0){ // trim trailing zeros j++; } for (i=len-1; i>=j; i--){ printf("%d", product[i]); } } else{ j=0; while (product[j]==0 && j<position){ // trim trailing zeros j++; } for (i=len-1; i>=j; i--){ if (i+1 == position){ // cause index in C language starts from 0 printf("."); } printf("%d", product[i]); } } printf("\n"); }system("pause");return 0;}
可是这个是利用了trick,我需要找到一个普遍的解法。于是我就跑去看看别人怎么实现的。
下面是http://www.cnblogs.com/BTMaster/p/3524992.html中的代码。
/* poj 1001 version:1.0 author:Knight Email:S.Knight.Work@gmail.com */#include<cstdio>#include<cstring>#include<cstdlib>#include<memory.h>using namespace std; char Result[200];//存R^N的结果 //大实数的乘法,乘数为FirMultiplier和SecMultiplier,结果存在Result中void HigRealMul(char* FirMultiplier, char* SecMultiplier, char* Result);//剔除实数尾部的无效0或小数点void CutInsignificantTail(char* StrR);//计算小数点在实数中的位数int CountPointIndex(char* StrR);//删除实数中的小数点,PointIndex为小数点在实数中从右向左数的第几位void DeletePoint(char* StrR, int PointIndex); int main(void){ char StrR[10];//R对应的字符串 int N; int i; int PointIndex = 0;//记录小数点在实数中从右向左数的第几位,如1.26在第3位,4在第0位 while(scanf("%s%d", StrR, &N) != EOF) { memset(Result, 0, 200); CutInsignificantTail(StrR); PointIndex = CountPointIndex(StrR); DeletePoint(StrR, PointIndex); strcpy(Result, StrR); for (i=2; i<=N; i++) { HigRealMul(Result, StrR, Result); } int Len = strlen(Result); if (Len -(PointIndex - 1) * N < 0) { printf("."); for (i = Len - (PointIndex - 1) * N; i<0; i++) { printf("0"); } } for (i=0; i<Len; i++) { //输出小数点 if (i == Len -(PointIndex - 1) * N) { printf("."); } printf("%c", Result[i]); } printf("\n"); //printf("%s\n", Result); //printf("%d\n", PointIndex); } return 0;} //大实数的乘法,乘数为FirMultiplier和SecMultiplier,结果存在Result中void HigRealMul(char* FirMultiplier, char* SecMultiplier, char* Result){ char TmpResult[200]; int i,j; int k = -1;//控制TmpResult[]下标 int FirLen = strlen(FirMultiplier); int SecLen = strlen(SecMultiplier); memset(TmpResult, '0', 200); //模拟乘法运算 for (i=SecLen-1; i>=0; i--) { k++; int FirMul; int SecMul = SecMultiplier[i] - '0'; int Carry;//进位 for (j=FirLen-1; j>=0; j--) { FirMul = FirMultiplier[j] - '0'; TmpResult[k + FirLen - 1 - j] += FirMul * SecMul % 10; Carry = FirMul * SecMul / 10 + (TmpResult[k + FirLen - 1 - j] - '0') / 10; TmpResult[k + FirLen - 1 - j] = (TmpResult[k + FirLen - 1 - j] - '0') % 10 + '0'; TmpResult[k + FirLen - j] += Carry; } } //防止某一位的值超过9 for (k=0; k<200; k++) { TmpResult[k + 1] += (TmpResult[k] - '0') / 10; TmpResult[k] = (TmpResult[k] - '0') % 10 + '0'; }//将设置字符串结束符 for (k=199; k>=0; k--) { if ('0' != TmpResult[k - 1]) { TmpResult[k] = '\0'; break; } } //将临时存储的答案TmpResult倒转变成我们熟悉的方式,存到Result中 for (i=strlen(TmpResult)-1,j=0; i>=0; i--,j++) { Result[j] = TmpResult[i]; } Result[j] = '\0'; } //剔除实数尾部的无效0或小数点void CutInsignificantTail(char* StrR){ int i; int PointIndex = CountPointIndex(StrR); int Len = strlen(StrR); if (0 == PointIndex) { if ('.' == StrR[Len - 1]) { StrR[Len - 1] = '\0'; } return; } for (i=Len-1; i>Len-1-PointIndex; i--) { if ('0' == StrR[i] || '.' == StrR[i]) { StrR[i] = '\0'; } else { return ; } }} //计算小数点在实数中的位数int CountPointIndex(char* StrR){ int i; int Index = 0; for (i = strlen(StrR); i>=0; i--) { if ('.' == StrR[i]) { break; } else { Index++; } } if (-1 == i) { Index = 0; } return Index; } //删除实数中的小数点void DeletePoint(char* StrR, int PointIndex){ int i; int Len = strlen(StrR); for (i=strlen(StrR)-PointIndex; i<Len; i++) { StrR[i] = StrR[i+1]; }}
另外,
这个讲得也挺好的,就是代码太啰嗦了。。。http://xiyueshiyi.blog.163.com/blog/static/203942233201411891210875/下面引申一些c++的知识:
C++中将string类型转换为int, float, double类型
# 方法一: 使用stringstream
stringstream在int或float类型转换为string类型的方法中已经介绍过, 这里也能用作将string类型转换为常用的数值类型。
Demo:
- #include <iostream>
- #include <sstream> //使用stringstream需要引入这个头文件
- using namespace std;
- //模板函数:将string类型变量转换为常用的数值类型(此方法具有普遍适用性)
- template <class Type>
- Type stringToNum(const string& str)
- {
- istringstream iss(str);
- Type num;
- iss >> num;
- return num;
- }
- int main(int argc, char* argv[])
- {
- string str("00801");
- cout << stringToNum<int>(str) << endl;
- system("pause");
- return 0;
- }
输出结果:
801
请按任意键继续. . .
#方法二:使用atoi()、 atil() 、atof()函数 -----------------实际上是char类型向数值类型的转换
注意:使用 atoi 的话,如果 string s 为空,返回值为0.则无法判断s是0还是空
1. atoi(): int atoi ( const char * str );
说明:Parses the C string str interpreting its content as an integral number, which is returned as an int value.
参数:str : C string beginning with the representation of an integral number.
返回值:1. 成功转换显示一个Int类型的值. 2. 不可转换的字符串返回0. 3.如果转换后缓冲区溢出,返回 INT_MAX orINT_MIN
Demo:
- #include <iostream>
- using namespace std;
- int main ()
- {
- int i;
- char szInput [256];
- cout<<"Enter a number: "<<endl;
- fgets ( szInput, 256, stdin );
- i = atoi (szInput);
- cout<<"The value entered is :"<<szInput<<endl;
- cout<<" The number convert is:"<<i<<endl;
- return 0;
- }
输出:
Enter a number: 48
The value entered is : 48
The number convert is: 48
2.aotl(): long int atol ( const char * str );
说明:C string str interpreting its content as an integral number, which is returned as a long int value(用法和atoi函数类似,返回值为long int)
3.atof(): double atof ( const char * str );
参数:C string beginning with the representation of a floating-point number.
返回值:1. 转换成功返回doublel类型的值 2.不能转换,返回0.0。 3.越界,返回HUGE_VAL
Demo:
- /* atof example: sine calculator */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- int main ()
- {
- double n,m;
- double pi=3.1415926535;
- char szInput [256];
- printf ( "Enter degrees: " );
- gets ( szInput );
- //char类型转换为double类型
- n = atof ( szInput );
- m = sin (n*pi/180);
- printf ( "The sine of %f degrees is %f\n" , n, m );
- return 0;
- }
- POJ1001 Exponentiation【高精度乘方】
- POJ1001 Exponentiation 高精度乘法
- POJ1001 Exponentiation 高精度
- POJ1001 Exponentiation,高精度乘法
- poj1001 Exponentiation --高精度
- poj1001-Exponentiation(高精度幂)
- POJ1001 Exponentiation【高精度】
- POJ1001 Exponentiation(高精度幂)
- POJ1001 Exponentiation 高精度
- POJ1001《Exponentiation》方法:模拟 高精度
- uva784 Exponentiation (实数高精度乘方)
- poj 1001 Exponentiation 高精度乘方
- POJ1001 Exponentiation--浮点数的高精度乘法
- 高精度乘法计算 poj1001 Exponentiation C代码
- POJ1001 Exponentiation
- POJ1001 Exponentiation
- POJ1001 Exponentiation
- POJ1001 Exponentiation
- Servlet 工作原理解析
- Spring IOC原理解读 面试必读
- android项目中context为空的问题解决
- ANDROID-当网络发生变化时使用BroadcastReceiver和service通知
- 文章标题
- POJ1001 Exponentiation【高精度乘方】
- 安装screenfetch
- [leetcode] 第一类--【数组】 题大纲
- 初步学习 ionic css 布局
- swift学习笔记之枚举
- 在windows中安装Jenkins并配置maven环境
- 社会化统计工具分享之Google分析、cnzz、51la、百度统计和Js比较
- java中四种引用类型
- Navicat for MySQL:快捷键整理