POJ1001 Exponenentiation

来源:互联网 发布:淘宝小二 灰色收入 编辑:程序博客网 时间:2024/05/22 05:30

POJ1001

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.

题意: 给定一个正实数R和正整数n,精确计算R^n。


分析: 在C\C++语言中,有符号正整数的位数最多为64位 表示范围 [-2^63, 2^63-1].实数最多也是64位(double)。对于大的数字精度可能不高。可以将正整数高精度四则运算模拟手工计算,用字符串模拟算法。

  在将一个实数转换成整数形式存储于字符串数组中设计如下几个步骤: 

  1.通过一个结构体Real 表示实数。 结构成员包括一个字符型数组 digits[]  ,和一个整型变量记录指数exp。考虑如何将字符串S构造成一个正实数。

    例如 s= "0.00670"  则digits[4] = {'0','0','0','6','7','0'};  exp = -5;

  2.将正整数数组规范化。去掉前后多余的0且同步更新指数值。 digits[2] = {'6','7'} ; exp = -4;

  3.R×R转化成 整数数相乘。

    例如 231×231 = 231×(2×10^2 + 3*10 + 1)

                = (23100+23100)+(2310+2310+2310)+(231)

    高精度乘法转换成高精度加法。字符串加法涉及到 对位,进位补零, 相加,清零(删除多余的0)。

  4.输出


C++代码实现

# include <iostream># include <cstring>using namespace std;const int MAX_DIGITS = 512;struct Real{char digits[MAX_DIGITS];int exp;};void ConstructReal(Real * real, char * str){real->exp = 0;if(str == NULL){strcpy(real->digits,"0"); return;}int i = 0;char * p = str;while(*p != '.')//碰到小数点{ //将该字符串中小数点前的数字存入数组digitsif(*p == '\0') //该实数为整数break;real->digits[i++] = *p;p++;}//让指针指向小数点后的第一位数字if(*p != '\0')p++;while(*p != '\0'){real->digits[i++] = *p++;real->exp--; //更新指数}real->digits[i] = '\0';}void NormalizeReal(Real * real){//去掉正整数数组后面多余的0int i = strlen(real->digits)-1;while(real->digits[i]=='0' && real->exp<0){real->digits[i] = '\0';real->exp++;i--;}//去掉前缀0char * p = real->digits;while(*p == '0')p++;strcpy(real->digits,p);if(real->digits[0] == '\0'){strcpy(real->digits,"0"); real->exp = 0;}}void ToSameDigits(char * str1, char * str2){int i;int len1 = strlen(str1), len2 = strlen(str2);int len = len1>len2?len1:len2;int less = len-len1;for(i = len1; i>=0; i--)str1[i+less+1] = str1[i]; //加1是为进位补零for(i = 0; i<=less; i++)str1[i] = '0';less = len-len2;for(i = len2; i>=0; i--)str2[i+less+1] = str2[i];for(i = 0; i<=less; i++)str2[i] = '0';} char * ClearFrontZero(char * str){  //清零(删除多余的0)char * p = str;while(*p == '0')p++;strcpy(str,p);if(str[0] == '\0'){str[0] = '0'; str[1] = '\0';}return str;} char * Plus(char * str1, char * str2, char * str3=NULL){int len,i;if(str3 == NULL)str3 = str1;elsestrcpy(str3,str1);ToSameDigits(str3,str2);len = strlen(str3);for(i = len-1; i>=0; i--){  //模拟手工计算,从后往前加str3[i] = str3[i]+str2[i]-'0';if(str3[i]>'9'){ //进位str3[i]-=10; str3[i-1]+=1;}}ClearFrontZero(str2);return ClearFrontZero(str3);}char * Multiply(char * str1, char * str2, char * str3){int i;char j;int len1 = strlen(str1), len2 = strlen(str2);strcpy(str3,"0");for(i = len2-1; i>=0; i--){  //外循环控制位置,从低位到高位for(j = 0;j<str2[i];j++){  //内循环控制加法次数Plus(str3,str1); ClearFrontZero(str1);}//一次外循环进一位str1[len1]= '0'; str1[len1+1]='\0'; len1++;}//还原str1str1[len1-len2] = '\0';return ClearFrontZero(str3);}void Multiply(Real * real1, Real * real2, Real * real3){Multiply(real1->digits, real2->digits, real3->digits);real3->exp = real1->exp+real2->exp;NormalizeReal(real3);}void PrintReal(Real * real, int tag){int i;int allLen = strlen(real->digits);int intLen = allLen+ real->exp;if(intLen>0){for(i = 0;i<=intLen;i++)cout<<real->digits[i];if(real->exp!=0)cout<<'.';char * p = real->digits+intLen;cout<<p;}else{if(tag == 1)cout<<'0';cout<<'.';for(i = 0; i>intLen; i--)cout<<'0';cout<<real->digits;}}  int main(){char s[MAX_DIGITS];int n; Real r1, r2, r3;int i;while(cin>>s>>n){ConstructReal(&r1,s); NormalizeReal(&r1);strcpy(r2.digits,r1.digits); r2.exp = r1.exp;strcpy(r3.digits,r1.digits); r3.exp = r1.exp;for(i= 1; i<n; i++){Multiply(&r1, &r2, &r3);strcpy(r1.digits,r3.digits); r1.exp = r3.exp;}PrintReal(&r3,0); cout<<endl;}return 0;}

运行结果:


    

原创粉丝点击