【poj】1001


【题目】


Exponentiation
Time Limit: 500MS Memory Limit: 10000K
Total Submissions: 123707 Accepted: 30202
Description


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.
Input


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.
Output


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.
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
Hint


If you don't know how to determine wheather encounted the end of input:
s is a string and n is an integer
C++


while(cin>>s>>n)


{


...


}


c


while(scanf("%s%d",s,&n)==2) //to see if the scanf read in as many items as you want


/*while(scanf(%s%d",s,&n)!=EOF) //this also work */


{


...


}


----------------------------------------------------------------------------------------------------------------------------------------------------------

这道题是我真正意义上的第一道题。所以写的很乱。估计再过上一段时间后连自己都看不懂。
大概思路:因为没有任何一种数据类型能够容纳这种高精度运算的结果。所以用数组来储存数据。求幂的实质就是n-1次乘法运算。运算之前把对字符串进行处理(提取小数点,同时记录指数),转化为整形数组。值得注意的是,要在整形数组后面开始储存。比如储存1234,是a[MAX-1]=4;a[MAX-2]=3;..这样有助于乘法运算的时候向前进一位。运算过程结束后再转化为字符串。重新加入小数点。
这一题做了很久很久,走了不少弯路,也就收货了一些经验:
1.代码的书写很重要。最好能形成层层缩进的结构。这样美观大方修改起来十分方便。
2.在写代码之前最好能够先详细构思一下。也就是所谓的建模。不要一有idea就马上动笔写下来。这次我就是很快把核心部分写了下来,却因为没有一个完整的架构。修修补补花了大量的时间。
3.审题。一开始看错题目、、、、满满的都是泪啊。
4.测试的时候没有进行全面的考虑。后期引用了这位兄弟的测试数据才ac。http://www.cnblogs.com/lililqth/p/3187758.html



  1 #include<stdio.h>

  2 #include<stdlib.h>

  3 #include<string.h>

  4 #include<math.h>

  5 #define MAX 500

  6 int pows(char [],char [],int ,int []);   //高精度计算pow         

  7 char *deal(char [],int ,int );    //处理计算好的字符串。

  8 int find(char []);     //寻找小数点所在位置,                     

  9 int cf(int [],int ,int [],int );  //高精度乘法                   

 10 int main(){

 11 char ins[MAX],des[MAX],*res;

 12 int n,index,len=0;

 13 int temp[MAX];

 14  while(scanf("%s%d",ins,&n)!=EOF)

 15  {

 16 

 17    index=find(ins);

 18    memset(temp,0,4*MAX);

 19    len=pows(ins,des,n,temp);

 20    if(len!=0)

 21     {

 22       res=deal(des,len,temp[MAX-1]);           //传递指数

 23       des[MAX-2]='\0';   //给倒数第二位加上字符串结束符

 24       printf("%s\n",res);

 25      }

 26     else return 0;

 27    

 28  }

 29 }

 30 int find(char des[MAX])

 31 {

 32   int i=0,index=-1;

 33    for(i=0;i<=strlen(des);i++)

 34     if(des[i]=='.'){

 35       index=i;

 36       return index;}

 37   return -1; //默认没有找到小数点

 38 }

 39 char *deal(char des[],int len,int en){

 40 int i,ts=0,zhi=0,k=0;

 41 //重新加入小数点

 42 zhi=MAX-3-(-en);   //小数点位置

 43  if((-en)==len)              {                          //-,小数点在刚好在第一位

 44    des[zhi]='.';

 45    return &des[zhi];       }

 46  else if((-en)>len)          {                          //二,数值小于1的情况,0.0xx;

 47      for(i=zhi;i<MAX-2-len;i++)

 48         des[i]='0';

 49         des[zhi]='.';

 50         return &des[zhi];  }

 51  else if(en==0)                                         //三,若此为整数,则直接返回字符串值

 52     return &des[MAX-2-len];

 53  else 

 54  {                                                      //四,数值大于1的情况

 55    for(i=MAX-2-len;i<=zhi;i++)                                                     

 56      des[i-1]=des[i];           //将小数点所在位置的前方往左挪一位。

 57    des[zhi]='.';

 58    return &des[MAX-3-len];

 59  }

 60 }

 61  

 62 int pows(char ins[MAX],char des[MAX],int n,int temp[MAX])

 63 {

 64   int t2[MAX]={0};

 65   int i=0,index=-1,k=0,m=0,ji=0,h=0,kj=0;

 66   int len=strlen(ins); 

 67   index=find(ins);

 68   m=len;

 69   if(n==0)      

 70   {   //n=0

 71   for(i=0;i<=len-1;i++)

 72       if(ins[i]!='0'){  //这个数不等于0                  

 73         temp[MAX-3]=1;

 74         temp[MAX-1]=0;

 75         break;       }

 76       else return 0;   //不可以计算0的0次幂

 77   }

 78   else if(n==1)

 79   {        //n=1

 80     for(i=0;i<=len-1;i++)    //从第一个位置开始遍历,检查前面是否有无意义的零

 81      if(ins[i]!='0')           

 82        break;

 83      if(i==len) 

 84       {   //整个字符串全为0

 85           m=1;

 86           temp[MAX-1]=0;  //表明这是一个整数

 87       }

 88      else    

 89       {   //前面有无意义的0,此处包含无0的情况

 90           m=len-i-1;

 91            //复制小数点之后的

 92           for(kj=MAX-3,h=len-1;h>index;h--,kj--)

 93             temp[kj]=ins[h]-48;

 94           temp[MAX-1]=-(len-index-1);  //记录指数

 95            //复制小数点之前的

 96           for(k=h-1;k>=i;kj--,k--)

 97             temp[kj]=ins[k]-48;                

 98       }    

 99     for(i=len-1,k=0;i>=0;i--) { //从后面开始扫描有没有无意义的0

100       if(ins[i]!='0')

101         break;        

102         k++;                    } //计算有多少个0

103     if(i<len-1)

104       {  //后面有无意义的0

105          if(ins[i]=='.') 

106            { //1.00样式

107              m -=k;

108              for(h=MAX-3;h>=MAX-2-m;h--)

109                temp[h]=temp[h-k];

110              temp[MAX-1]=0;   //标记为整数

111            }

112          else

113            { //1.**00的样式

114              m -=k;

115              for(h=MAX-3;h>=MAX-2-m;h--)

116                temp[h]=temp[h-k];

117              temp[MAX-1] +=k;  //修改指数

118            }    

119       }

120   }

121   else  

122   {         //n>=2

123     if(index==-1) 

124     {           //一。整数,没有找到小数点         

125       for(i=0;i<=len-1;i++)   {

126         temp[MAX-2-len+i]=ins[i]-48;

127         t2[MAX-2-len+i]=ins[i]-48;

128                               }

129     }

130     else

131     {           //二找到小数点

132        if(index==0)

133         {  //处理形式为 。**的形式的实数

134           for(i=len;i>=1;i--)

135              ins[i]=ins[i-1];

136           ins[0]='0'; 

137           len++;

138         }           

139        i=len-1;                   

140        while(ins[i]=='0')  i--;   //从最后一个字符开始检查,检查最后是否带有无意义的0    

141        if(i<len-1)        

142        {         //******后面带有无意义的0          

143 

144          if(ins[i]=='.')   

145          {               //-----1.00的形式

146            len=i;    //连同小数点一起抛弃

147            index=-1; //将该数标记为整数

148            for(i=0;i<=len-1;i++)   

149            {    //复制到整形数组中

150              temp[MAX-2-len+i]=ins[i]-48;

151              t2[MAX-2-len+i]=ins[i]-48;

152            }

153          }

154          else 

155          {               //------1.**000的形式

156            len=i+1; 

157             for(i=0;i<=index-1;i++)     {         //用两个for循环将字符串转换为整形数组,并且要将从右边开始写入

158               temp[MAX-1-len+i]=ins[i]-48;         //从整形数组的倒数第三位开始储存

159               t2[MAX-1-len+i]=ins[i]-48; }

160                                           //跳过小数点

161             for(k=index+1;k<=len-1;k++,i++){

162               temp[MAX-1-len+i]=ins[k]-48;

163               t2[MAX-1-len+i]=ins[k]-48;    }                   

164          }

165        }

166        else

167        {         //******后面没有无意义的0              

168     

169           for(i=0;i<=index-1;i++)      {         //用两个for循环将字符串转换为整形数组,并且要将从右边开始写入

170              temp[MAX-1-len+i]=ins[i]-48;         //从整形数组的倒数第三位开始储存

171              t2[MAX-1-len+i]=ins[i]-48;}

172                                  

173           for(k=index+1;k<=len-1;k++,i++) {   //跳过小数点

174             temp[MAX-1-len+i]=ins[k]-48;

175             t2[MAX-1-len+i]=ins[k]-48;    }         

176        }

177     }

178     //在数组的最后一位记录这两个数的指数

179     if(index==-1)

180     {      //如果为整数则将该指数部分置为0

181     temp[MAX-1]=0;

182     t2[MAX-1]=0;

183     k=len;

184     m=len;       

185     }

186     else       

187     {   //不为整数

188     temp[MAX-1]=index-len+1;

189     t2[MAX-1]=index-len+1;

190     k=len-1;

191     m=len-1;    

192     }

193    for(i=0;i<n-1;i++)     //pow的核心

194     {    //需要n-1次乘法

195        cf(temp,m,t2,k);     //cf返回temp数组中所含数的长度

196        for(ji=0;ji<=MAX-3;ji++)

197         {   //计算temp中的数的长度

198            if(temp[ji]!=0){

199             m=MAX-ji-2;

200            break;   }

201         }

202     }

203   }

204   //重新将字符转换为数值

205 for(i=MAX-3;i>=MAX-3-m+1;i--)   //从整形数组倒数第三位开始复制到字符串的倒数第三位

206 des[i]=temp[i]+48;

207 return m;     //返回字符串的长度

208 } 

209 int cf(int temp[MAX],int m,int src[MAX],int k){

210      int t[MAX]={0};    

211      int i=0,num=0;

212      int sr=0,tmp=MAX-3,j=sr;

213      temp[MAX-2]=0; //防止k在边界时溢出.在倒数第二位储存0

214      src[MAX-2]=0;

215   // 用两个for循环来完成两个数的相乘

216   for(sr=MAX-3;sr>=MAX-m-2;sr--)        //数组的倒数第三位储存数的最低位

217   {

218    for(tmp=MAX-3,j=sr;tmp>=MAX-2-m;tmp--,j--)  //src从个位开始每位乘以temp中的每一位 //之所以使j=sr--我们在计算两数相乘时总会将下一行的数向左挪一位。

219     t[j] +=src[sr]*temp[tmp];

220   }

221   //将t复制到temp中

222   for(i=MAX-3;i>=sr-m+2;i--)

223     temp[i]=t[i];

224   for(i=MAX-3;i>=sr-m;i--) 

225   {   // 处理temp中的数,过十进一,每一位只保留个位,需要注意的是有可能是进百位。故要把i提前到temp左端的前两格

226     temp[i] +=num;

227     num=  (temp[i]-temp[i]%10)/10; //保存当前一位的十位数和百位数.如128保留12;

228     temp[i]=temp[i]%10;     //进位后,只保存个位数

229   }

230    temp[MAX-1] +=src[MAX-1];  //处理指数部分的相乘

231   return 0;

232 }
View Code

 

你可能感兴趣的:(poj)