poj 1001Exponentiation 高精度

//这题用高精度乘法算

#include <iostream>

#include <cstring>

using namespace std;

#define X 140

void multiply(int num[],int a[],int m)   //高精度乘法运算

{

       int s[X];

       memset(s,0,sizeof(s));

       int i,j;

       for(j=0;j<m;j++)

              for(i=0;i<126;i++)

                     s[i+j] += num[i]*a[j];    //核心算法,把乘完的结果保存到数组s[]中

 

       int carry = 0;         //表进位

       for(i=0;i<X;i++)

       {

              num[i] = (carry+s[i])%10;

              carry = (carry+s[i])/10;

       }

}

int main()

{

       freopen("sum.in","r",stdin);

       freopen("sum.out","w",stdout);

       int n,i;

       char r[7];

       while(cin>>r>>n)

       {

              int num[X];

              for(i=0;i<X;i++)

                     num[i] = 0;

 

              int a[7];

              int dot = 0;     //记录小数点位数

              int m = 0;

              for(i=5;i>=0;i--)    //把字符数组转换为int型数组

              {

                     if(r[i]!='.')

                     {

                            a[m] = r[i]-'0';

                            num[m++] = r[i]-'0';

                     }

                     else

                            dot = i;    //记录小数点位置

              }

 

              int q = 0;        //记录如20.000时整数部分的零的个数

              for(i=dot-1;i>=0;i--)      //从小数点前一位开始往前算

              {

                     if(r[i]=='0')

                            q++;

                     else

                            break;

              }

             

              for(i=5;i>=0;i--)

                     if(r[i]!='0')

                            break;

              dot=i-dot;

              int len = dot*n;             //算完后整个数的小数部分位数

 

              for(i=1;i<n;i++)            //因为之前已把一个数保存到num[]中了,这里只需算n-1次

                     multiply(num,a,m);       //利用高精度乘法运算

 

              for(i=X-1;i>=0;i--)        //去掉后置零

                     if(num[i]!=0)

                            break;

              int rear = i;                   //记录后置零位置

 

              for(i=0;i<=rear;i++)      //去掉前置零

                     if(num[i]!=0)

                            break;

              int front = i;                 //记录前置零位置

 

              if(rear-front+1<len)//当0.0123^3=.000001860867类型时,小数点前面的零已去掉,需要补上

              {

                     cout<<".";             //0.12类不需要输入0

 

                     for(i=len-rear+front-1;i>0;i--)      //小数点后差的零补上

                            cout<<0;

 

                     for(i=rear;i>=front;i--)

                            cout<<num[i];

 

                     cout<<endl;

              }

 

              /*else if(rear-front+1==len)想了一下,这个可以不要,

              因为只有指数为一时才会这样,但这时不会进入这个循环内的,又提交一次后发现是对的

              {

                     cout<<".";

                     for(i=rear;i>=front;i--)

                            cout<<num[i];

                     cout<<endl;

              }

              */

              else         //小数部分不需补零

              {

                     for(i=rear;i>=front;i--)

                     {

                            cout<<num[i];

                            if(i-front==len&&len)   //如果到了小数点位置,输入.

                            {

                                   cout<<".";

                            }

                            else if(!len&&i-front==len)  

                            {            //如果输入的是20.00类,因为整数部分的零同样去了,需补上

                                   for(int j=0;j<q*n;j++)

                                          cout<<0;

                            }

                     }

                     cout<<endl;

              }

       }

 

       return 0;

}

posted @ 2012-03-20 14:42  yejinru  阅读(239)  评论(0编辑  收藏  举报